mirror of
https://github.com/Anime-Game-Servers/Grasscutter-Quests.git
synced 2024-11-23 04:29:42 +00:00
[Refactoring] Use AnimeGameLua for lua parsing and lua script handling
* Also added support to read overwrite script files from an overwrite location
This commit is contained in:
parent
a48b55ec1d
commit
740e12b05c
@ -96,8 +96,13 @@ dependencies {
|
||||
implementation group: 'org.quartz-scheduler', name: 'quartz-jobs', version: '2.3.2'
|
||||
implementation 'org.apache.commons:commons-lang3:3.14.0'
|
||||
|
||||
implementation("org.anime_game_servers.core:gi:0.1")
|
||||
implementation("org.anime_game_servers:luaj:3.0.3")
|
||||
implementation("org.anime_game_servers:JNLua_GC:0.1.0")
|
||||
implementation("org.anime_game_servers.lua:base:0.1")
|
||||
implementation("org.anime_game_servers.lua:GIlua:0.1")
|
||||
implementation("org.anime_game_servers.lua:LuaJEngine:0.1")
|
||||
implementation("org.anime_game_servers.lua:JNLuaEngine:0.1")
|
||||
|
||||
implementation("org.anime_game_servers.multi_proto:gi-jvm:0.1.32")
|
||||
|
||||
@ -106,7 +111,6 @@ dependencies {
|
||||
|
||||
implementation group: 'io.javalin', name: 'javalin', version: '4.6.4'
|
||||
implementation group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.13.3'
|
||||
//implementation("pro.streem.pbandk:pbandk-runtime:0.14.2")
|
||||
|
||||
protobuf files('proto/')
|
||||
|
||||
|
@ -117,7 +117,6 @@ public final class Grasscutter {
|
||||
|
||||
// Load all resources.
|
||||
Grasscutter.updateDayOfWeek();
|
||||
ScriptLoader.init();
|
||||
ResourceLoader.loadAll();
|
||||
|
||||
// Generate handbooks.
|
||||
|
@ -5,8 +5,6 @@ import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.game.world.Scene;
|
||||
import emu.grasscutter.game.world.SceneGroupInstance;
|
||||
import emu.grasscutter.scripts.data.SceneGroup;
|
||||
import emu.grasscutter.utils.Position;
|
||||
import lombok.Setter;
|
||||
import lombok.val;
|
||||
|
||||
|
@ -86,6 +86,7 @@ public class ConfigContainer {
|
||||
public String data = "./data/";
|
||||
public String packets = "./packets/";
|
||||
public String scripts = "resources:Scripts/";
|
||||
public String scriptOverwrites = "./overwrites/Scripts/";
|
||||
public String plugins = "./plugins/";
|
||||
public String cache = "./server/cache/";
|
||||
|
||||
|
@ -31,7 +31,6 @@ import emu.grasscutter.game.quest.RewindData;
|
||||
import emu.grasscutter.game.quest.TeleportData;
|
||||
import emu.grasscutter.game.world.GroupReplacementData;
|
||||
import emu.grasscutter.game.quest.enums.QuestCond;
|
||||
import emu.grasscutter.scripts.data.DummyPoint;
|
||||
import emu.grasscutter.utils.Utils;
|
||||
import emu.grasscutter.data.excels.*;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntMap;
|
||||
@ -46,6 +45,8 @@ import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.experimental.Tolerate;
|
||||
import lombok.val;
|
||||
import org.anime_game_servers.gi_lua.models.scene.DummyPoint;
|
||||
import org.anime_game_servers.gi_lua.models.scene.SceneGroupReplacement;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@ -188,7 +189,7 @@ public class GameData {
|
||||
@Getter private static final Int2ObjectMap<DropTableExcelConfigData> dropTableExcelConfigDataMap = new Int2ObjectOpenHashMap<>();
|
||||
@Getter private static final Int2ObjectMap<MonsterMapping> monsterMappingMap = new Int2ObjectOpenHashMap<>();
|
||||
@Getter private static final Int2ObjectMap<ActivityCondGroup> activityCondGroupMap = new Int2ObjectOpenHashMap<>();
|
||||
@Getter private static final Int2ObjectMap<GroupReplacementData> groupReplacements = new Int2ObjectOpenHashMap<>();
|
||||
@Getter private static final Int2ObjectMap<SceneGroupReplacement> groupReplacements = new Int2ObjectOpenHashMap<>();
|
||||
|
||||
// Cache
|
||||
@Getter private static final IntList scenePointIdList = new IntArrayList();
|
||||
|
@ -30,15 +30,10 @@ import emu.grasscutter.game.quest.RewindData;
|
||||
import emu.grasscutter.game.quest.TeleportData;
|
||||
import emu.grasscutter.game.quest.enums.QuestCond;
|
||||
import emu.grasscutter.game.quest.enums.QuestContent;
|
||||
import emu.grasscutter.game.world.GroupReplacementData;
|
||||
import emu.grasscutter.game.world.SpawnDataEntry;
|
||||
import emu.grasscutter.game.world.SpawnDataEntry.GridBlockId;
|
||||
import emu.grasscutter.game.world.SpawnDataEntry.SpawnGroupEntry;
|
||||
import emu.grasscutter.scripts.EntityControllerScriptManager;
|
||||
import emu.grasscutter.scripts.SceneIndexManager;
|
||||
import emu.grasscutter.scripts.ScriptLoader;
|
||||
import emu.grasscutter.scripts.data.DummyPoint;
|
||||
import emu.grasscutter.scripts.lua_engine.ScriptType;
|
||||
import emu.grasscutter.scripts.*;
|
||||
import emu.grasscutter.utils.FileUtils;
|
||||
import emu.grasscutter.utils.JsonUtils;
|
||||
import emu.grasscutter.utils.TsvUtils;
|
||||
@ -48,13 +43,14 @@ import it.unimi.dsi.fastutil.ints.IntArrayList;
|
||||
import it.unimi.dsi.fastutil.ints.IntArraySet;
|
||||
import lombok.val;
|
||||
|
||||
import org.anime_game_servers.gi_lua.models.loader.SceneReplacementScriptLoadParams;
|
||||
import org.anime_game_servers.gi_lua.models.loader.ShardQuestScriptLoadParams;
|
||||
import org.anime_game_servers.gi_lua.models.scene.SceneGroupReplacement;
|
||||
import org.reflections.Reflections;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.file.DirectoryStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.LinkOption;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
@ -755,7 +751,6 @@ public class ResourceLoader {
|
||||
private static void loadScriptData(){
|
||||
loadQuestShareConfig();
|
||||
loadGroupReplacements();
|
||||
loadDummyPoints();
|
||||
}
|
||||
|
||||
private static void loadQuestShareConfig(){
|
||||
@ -766,20 +761,18 @@ public class ResourceLoader {
|
||||
stream.forEach(path -> {
|
||||
val matcher = pattern.matcher(path.getFileName().toString());
|
||||
if (!matcher.find()) return;
|
||||
val questId = Integer.parseInt(matcher.group(1));
|
||||
|
||||
val cs = ScriptLoader.getScript("Quest/Share/"+path.getFileName().toString(), ScriptType.DATA_STORAGE);
|
||||
if (cs == null) return;
|
||||
|
||||
try{
|
||||
cs.evaluate();
|
||||
val sharedQuestParams = new ShardQuestScriptLoadParams(questId);
|
||||
if(!ScriptSystem.getScriptLoader().loadData(sharedQuestParams, script -> {
|
||||
// these are Map<String, class>
|
||||
val teleportDataMap = cs.getGlobalVariableMap("quest_data", TeleportData.class);
|
||||
val rewindDataMap = cs.getGlobalVariableMap("rewind_data", RewindData.class);
|
||||
val teleportDataMap = script.getGlobalVariableMap("quest_data", TeleportData.class);
|
||||
val rewindDataMap = script.getGlobalVariableMap("rewind_data", RewindData.class);
|
||||
|
||||
// convert them to Map<Integer, class> and cache
|
||||
GameData.getTeleportDataMap().putAll(teleportDataMap.entrySet().stream().collect(Collectors.toMap(entry -> Integer.valueOf(entry.getKey()), Entry::getValue)));
|
||||
GameData.getRewindDataMap().putAll(rewindDataMap.entrySet().stream().collect(Collectors.toMap(entry -> Integer.valueOf(entry.getKey()), Entry::getValue)));
|
||||
|
||||
} catch (Throwable e){
|
||||
})) {
|
||||
logger.error("Error while loading Quest Share Config: {}", path.getFileName().toString());
|
||||
}
|
||||
});
|
||||
@ -793,38 +786,6 @@ public class ResourceLoader {
|
||||
}
|
||||
}
|
||||
|
||||
private static void loadDummyPoints(){
|
||||
// Load from scene scripts
|
||||
|
||||
try(val stream = Files.newDirectoryStream(getResourcePath("Scripts/Scene/"), p -> Files.isDirectory(p, LinkOption.NOFOLLOW_LINKS))) {
|
||||
stream.forEach(path -> {
|
||||
int sceneId = Integer.parseInt(path.getFileName().toString());
|
||||
val targetScript = "Scene/"+sceneId+"/scene"+sceneId+"_dummy_points.lua";
|
||||
val targetPath = FileUtils.getScriptPath(targetScript);
|
||||
if(Files.notExists(targetPath)) return;
|
||||
val cs = ScriptLoader.getScript(targetScript, ScriptType.DATA_STORAGE);
|
||||
if (cs == null) return;
|
||||
|
||||
try{
|
||||
cs.evaluate();
|
||||
val teleportDataMap = cs.getGlobalVariableMap("dummy_points",DummyPoint.class);
|
||||
GameData.getDummyPointMap().put(sceneId, teleportDataMap);
|
||||
logger.info("Loaded {} dummy points for scene {}.", teleportDataMap.size(), sceneId);
|
||||
} catch (Throwable e){
|
||||
logger.error("Error while loading Quest Share Config: {}", path.getFileName().toString());
|
||||
}
|
||||
});
|
||||
} catch (IOException e) {
|
||||
logger.error("Error loading Quest Share Config: no files found");
|
||||
return;
|
||||
}
|
||||
if (GameData.getDummyPointMap() == null || GameData.getDummyPointMap().isEmpty()) {
|
||||
logger.error("No scene dummy points loaded!");
|
||||
} else {
|
||||
logger.info("Loaded dummy points for {} scenes.", GameData.getDummyPointMap().size());
|
||||
}
|
||||
}
|
||||
|
||||
private static void loadGadgetMappings() {
|
||||
try {
|
||||
val gadgetMap = GameData.getGadgetMappingMap();
|
||||
@ -931,33 +892,15 @@ public class ResourceLoader {
|
||||
}
|
||||
|
||||
private static void loadGroupReplacements(){
|
||||
|
||||
val cs = ScriptLoader.getScript("Scene/groups_replacement.lua", ScriptType.DATA_STORAGE);
|
||||
if (cs == null) {
|
||||
logger.error("Error while loading Group Replacements: file not found");
|
||||
return;
|
||||
}
|
||||
|
||||
try{
|
||||
cs.evaluate();
|
||||
val scriptParams = new SceneReplacementScriptLoadParams();
|
||||
if(!ScriptSystem.getScriptLoader().loadData(scriptParams, script -> {
|
||||
// these are Map<String, class>
|
||||
var replacementsMap = cs.getGlobalVariableMap("replacements", GroupReplacementData.class);
|
||||
var replacementsMap = script.getGlobalVariableMap("replacements", SceneGroupReplacement.class);
|
||||
// convert them to Map<Integer, class> and cache
|
||||
GameData.getGroupReplacements().putAll(replacementsMap.entrySet().stream().collect(Collectors.toMap(entry -> Integer.valueOf(entry.getValue().getId()), Entry::getValue)));
|
||||
|
||||
} catch (Throwable e){
|
||||
})) {
|
||||
logger.error("Error while loading Group Replacements");
|
||||
}
|
||||
|
||||
if (GameData.getGroupReplacements() == null || GameData.getGroupReplacements().isEmpty()) {
|
||||
logger.error("No Group Replacements loaded!");
|
||||
return;
|
||||
} else {
|
||||
logger.debug("Loaded {} group replacements.", GameData.getGroupReplacements().size());
|
||||
GameData.getGroupReplacements().forEach((group, groups) -> {
|
||||
logger.debug("{} -> {}", group, groups.getReplace_groups().stream().map(String::valueOf).collect(Collectors.joining(",")));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// BinOutput configs
|
||||
|
@ -2,10 +2,10 @@ package emu.grasscutter.data.binout;
|
||||
|
||||
import com.github.davidmoten.rtreemulti.RTree;
|
||||
import com.github.davidmoten.rtreemulti.geometry.Geometry;
|
||||
import emu.grasscutter.scripts.data.SceneGroup;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.FieldDefaults;
|
||||
import org.anime_game_servers.gi_lua.models.scene.group.SceneGroup;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -1,8 +1,6 @@
|
||||
package emu.grasscutter.data.binout;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import emu.grasscutter.scripts.data.SceneGroup;
|
||||
import emu.grasscutter.utils.Position;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -5,7 +5,7 @@ import emu.grasscutter.game.activity.PlayerActivityData;
|
||||
import emu.grasscutter.game.activity.condition.ActivityCondition;
|
||||
import emu.grasscutter.game.activity.condition.ActivityConditionBaseHandler;
|
||||
import emu.grasscutter.game.quest.GameQuest;
|
||||
import emu.grasscutter.game.quest.enums.QuestState;
|
||||
import org.anime_game_servers.core.gi.enums.QuestState;
|
||||
|
||||
import static emu.grasscutter.game.activity.condition.ActivityConditions.NEW_ACTIVITY_COND_QUEST_FINISH;
|
||||
|
||||
|
@ -2,8 +2,6 @@ package emu.grasscutter.game.dungeons;
|
||||
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.data.GameData;
|
||||
import emu.grasscutter.data.binout.ScenePointEntry;
|
||||
import emu.grasscutter.data.common.PointData;
|
||||
import emu.grasscutter.data.excels.DungeonData;
|
||||
import emu.grasscutter.data.excels.DungeonElementChallengeData;
|
||||
import emu.grasscutter.data.excels.DungeonPassConfigData;
|
||||
@ -19,8 +17,6 @@ import emu.grasscutter.game.quest.enums.LogicType;
|
||||
import emu.grasscutter.game.quest.enums.QuestContent;
|
||||
import emu.grasscutter.game.world.Scene;
|
||||
import emu.grasscutter.net.proto.TrialAvatarGrantRecordOuterClass;
|
||||
import emu.grasscutter.scripts.constants.EventType;
|
||||
import emu.grasscutter.scripts.data.ScriptArgs;
|
||||
import emu.grasscutter.server.packet.send.PacketDungeonDataNotify;
|
||||
import emu.grasscutter.server.packet.send.PacketDungeonReviseLevelNotify;
|
||||
import emu.grasscutter.server.packet.send.PacketDungeonWayPointNotify;
|
||||
@ -34,6 +30,8 @@ import lombok.NonNull;
|
||||
import lombok.Setter;
|
||||
import lombok.val;
|
||||
import messages.scene.entity.WeeklyBossResinDiscountInfo;
|
||||
import org.anime_game_servers.gi_lua.models.ScriptArgs;
|
||||
import org.anime_game_servers.gi_lua.models.constants.EventType;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.*;
|
||||
|
@ -9,16 +9,16 @@ import emu.grasscutter.game.entity.GameEntity;
|
||||
import emu.grasscutter.game.props.ElementReactionType;
|
||||
import emu.grasscutter.game.props.WatcherTriggerType;
|
||||
import emu.grasscutter.game.world.Scene;
|
||||
import emu.grasscutter.scripts.constants.EventType;
|
||||
import emu.grasscutter.scripts.data.SceneGroup;
|
||||
import emu.grasscutter.scripts.data.SceneTrigger;
|
||||
import emu.grasscutter.scripts.data.ScriptArgs;
|
||||
import emu.grasscutter.server.packet.send.PacketDungeonChallengeBeginNotify;
|
||||
import emu.grasscutter.server.packet.send.PacketDungeonChallengeFinishNotify;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import lombok.val;
|
||||
import org.anime_game_servers.gi_lua.models.ScriptArgs;
|
||||
import org.anime_game_servers.gi_lua.models.constants.EventType;
|
||||
import org.anime_game_servers.gi_lua.models.scene.group.SceneGroup;
|
||||
import org.anime_game_servers.gi_lua.models.scene.group.SceneTrigger;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@ -58,7 +58,7 @@ public class WorldChallenge {
|
||||
* Get the monster group id spawned by the challenge
|
||||
*/
|
||||
public int getGroupId(){
|
||||
return group!=null ? group.getId() : 0;
|
||||
return group!=null ? group.getGroupInfo().getId() : 0;
|
||||
}
|
||||
|
||||
|
||||
@ -184,7 +184,7 @@ public class WorldChallenge {
|
||||
|
||||
public void onGroupTriggerDeath(SceneTrigger trigger){
|
||||
if(!inProgress()) return;
|
||||
if(Optional.ofNullable(trigger.getCurrentGroup()).filter(g -> g.getId() == getGroupId()).isEmpty()) return;
|
||||
if(trigger.getGroupId() != getGroupId()) return;
|
||||
|
||||
Optional.ofNullable(this.challengeTriggers.get(TriggerGroupTriggerTrigger.class))
|
||||
.ifPresent(t -> t.onGroupTrigger(this, trigger));
|
||||
|
@ -8,8 +8,8 @@ import emu.grasscutter.game.dungeons.challenge.ChallengeScoreInfo;
|
||||
import emu.grasscutter.game.dungeons.challenge.WorldChallenge;
|
||||
import emu.grasscutter.game.dungeons.challenge.enums.ChallengeType;
|
||||
import emu.grasscutter.game.world.Scene;
|
||||
import emu.grasscutter.scripts.data.SceneGroup;
|
||||
import lombok.val;
|
||||
import org.anime_game_servers.gi_lua.models.scene.group.SceneGroup;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
|
@ -6,7 +6,7 @@ import emu.grasscutter.game.dungeons.challenge.WorldChallenge;
|
||||
import emu.grasscutter.game.dungeons.challenge.enums.ChallengeType;
|
||||
import emu.grasscutter.game.dungeons.challenge.trigger.ChallengeTrigger;
|
||||
import emu.grasscutter.game.world.Scene;
|
||||
import emu.grasscutter.scripts.data.SceneGroup;
|
||||
import org.anime_game_servers.gi_lua.models.scene.group.SceneGroup;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -6,7 +6,7 @@ import emu.grasscutter.game.dungeons.challenge.WorldChallenge;
|
||||
import emu.grasscutter.game.dungeons.challenge.enums.ChallengeType;
|
||||
import emu.grasscutter.game.dungeons.challenge.trigger.TimeTrigger;
|
||||
import emu.grasscutter.game.world.Scene;
|
||||
import emu.grasscutter.scripts.data.SceneGroup;
|
||||
import org.anime_game_servers.gi_lua.models.scene.group.SceneGroup;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
@ -7,8 +7,8 @@ import emu.grasscutter.game.dungeons.challenge.enums.ChallengeType;
|
||||
import emu.grasscutter.game.dungeons.challenge.trigger.ElementReactionTrigger;
|
||||
import emu.grasscutter.game.props.ElementReactionType;
|
||||
import emu.grasscutter.game.world.Scene;
|
||||
import emu.grasscutter.scripts.data.SceneGroup;
|
||||
import lombok.val;
|
||||
import org.anime_game_servers.gi_lua.models.scene.group.SceneGroup;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.IntStream;
|
||||
|
@ -7,7 +7,7 @@ import emu.grasscutter.game.dungeons.challenge.enums.ChallengeType;
|
||||
import emu.grasscutter.game.dungeons.challenge.trigger.FatherTrigger;
|
||||
import emu.grasscutter.game.dungeons.challenge.trigger.TimeTrigger;
|
||||
import emu.grasscutter.game.world.Scene;
|
||||
import emu.grasscutter.scripts.data.SceneGroup;
|
||||
import org.anime_game_servers.gi_lua.models.scene.group.SceneGroup;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
@ -7,7 +7,7 @@ import emu.grasscutter.game.dungeons.challenge.enums.ChallengeType;
|
||||
import emu.grasscutter.game.dungeons.challenge.trigger.ElementReactionTrigger;
|
||||
import emu.grasscutter.game.dungeons.challenge.trigger.TimeTrigger;
|
||||
import emu.grasscutter.game.world.Scene;
|
||||
import emu.grasscutter.scripts.data.SceneGroup;
|
||||
import org.anime_game_servers.gi_lua.models.scene.group.SceneGroup;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
@ -6,8 +6,8 @@ import emu.grasscutter.game.dungeons.challenge.WorldChallenge;
|
||||
import emu.grasscutter.game.dungeons.challenge.enums.ChallengeType;
|
||||
import emu.grasscutter.game.dungeons.challenge.trigger.KillMonsterTrigger;
|
||||
import emu.grasscutter.game.world.Scene;
|
||||
import emu.grasscutter.scripts.data.SceneGroup;
|
||||
import lombok.val;
|
||||
import org.anime_game_servers.gi_lua.models.scene.group.SceneGroup;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
@ -7,8 +7,8 @@ import emu.grasscutter.game.dungeons.challenge.enums.ChallengeType;
|
||||
import emu.grasscutter.game.dungeons.challenge.trigger.ElementReactionTrigger;
|
||||
import emu.grasscutter.game.dungeons.challenge.trigger.KillMonsterTrigger;
|
||||
import emu.grasscutter.game.world.Scene;
|
||||
import emu.grasscutter.scripts.data.SceneGroup;
|
||||
import lombok.val;
|
||||
import org.anime_game_servers.gi_lua.models.scene.group.SceneGroup;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
@ -7,8 +7,8 @@ import emu.grasscutter.game.dungeons.challenge.enums.ChallengeType;
|
||||
import emu.grasscutter.game.dungeons.challenge.trigger.GuardTrigger;
|
||||
import emu.grasscutter.game.dungeons.challenge.trigger.KillMonsterTrigger;
|
||||
import emu.grasscutter.game.world.Scene;
|
||||
import emu.grasscutter.scripts.data.SceneGroup;
|
||||
import lombok.val;
|
||||
import org.anime_game_servers.gi_lua.models.scene.group.SceneGroup;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
@ -8,8 +8,8 @@ import emu.grasscutter.game.dungeons.challenge.trigger.GuardTrigger;
|
||||
import emu.grasscutter.game.dungeons.challenge.trigger.KillMonsterTrigger;
|
||||
import emu.grasscutter.game.dungeons.challenge.trigger.TimeTrigger;
|
||||
import emu.grasscutter.game.world.Scene;
|
||||
import emu.grasscutter.scripts.data.SceneGroup;
|
||||
import lombok.val;
|
||||
import org.anime_game_servers.gi_lua.models.scene.group.SceneGroup;
|
||||
|
||||
import java.util.List;
|
||||
import static emu.grasscutter.game.dungeons.challenge.enums.ChallengeType.CHALLENGE_GUARD_HP;
|
||||
|
@ -7,8 +7,8 @@ import emu.grasscutter.game.dungeons.challenge.enums.ChallengeType;
|
||||
import emu.grasscutter.game.dungeons.challenge.trigger.TimeTrigger;
|
||||
import emu.grasscutter.game.dungeons.challenge.trigger.KillMonsterTrigger;
|
||||
import emu.grasscutter.game.world.Scene;
|
||||
import emu.grasscutter.scripts.data.SceneGroup;
|
||||
import lombok.val;
|
||||
import org.anime_game_servers.gi_lua.models.scene.group.SceneGroup;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
@ -7,8 +7,8 @@ import emu.grasscutter.game.dungeons.challenge.enums.ChallengeType;
|
||||
import emu.grasscutter.game.dungeons.challenge.trigger.KillMonsterTrigger;
|
||||
import emu.grasscutter.game.dungeons.challenge.trigger.TimeTrigger;
|
||||
import emu.grasscutter.game.world.Scene;
|
||||
import emu.grasscutter.scripts.data.SceneGroup;
|
||||
import lombok.val;
|
||||
import org.anime_game_servers.gi_lua.models.scene.group.SceneGroup;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
@ -6,7 +6,7 @@ import emu.grasscutter.game.dungeons.challenge.WorldChallenge;
|
||||
import emu.grasscutter.game.dungeons.challenge.enums.ChallengeType;
|
||||
import emu.grasscutter.game.dungeons.challenge.trigger.DamageCountTrigger;
|
||||
import emu.grasscutter.game.world.Scene;
|
||||
import emu.grasscutter.scripts.data.SceneGroup;
|
||||
import org.anime_game_servers.gi_lua.models.scene.group.SceneGroup;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
@ -6,7 +6,7 @@ import emu.grasscutter.game.dungeons.challenge.WorldChallenge;
|
||||
import emu.grasscutter.game.dungeons.challenge.enums.ChallengeType;
|
||||
import emu.grasscutter.game.dungeons.challenge.trigger.TimeTrigger;
|
||||
import emu.grasscutter.game.world.Scene;
|
||||
import emu.grasscutter.scripts.data.SceneGroup;
|
||||
import org.anime_game_servers.gi_lua.models.scene.group.SceneGroup;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
@ -7,8 +7,8 @@ import emu.grasscutter.game.dungeons.challenge.enums.ChallengeType;
|
||||
import emu.grasscutter.game.dungeons.challenge.trigger.KillMonsterTrigger;
|
||||
import emu.grasscutter.game.dungeons.challenge.trigger.TimeTrigger;
|
||||
import emu.grasscutter.game.world.Scene;
|
||||
import emu.grasscutter.scripts.data.SceneGroup;
|
||||
import lombok.val;
|
||||
import org.anime_game_servers.gi_lua.models.scene.group.SceneGroup;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
@ -5,7 +5,7 @@ import emu.grasscutter.game.dungeons.challenge.ChallengeScoreInfo;
|
||||
import emu.grasscutter.game.dungeons.challenge.WorldChallenge;
|
||||
import emu.grasscutter.game.dungeons.challenge.enums.ChallengeType;
|
||||
import emu.grasscutter.game.world.Scene;
|
||||
import emu.grasscutter.scripts.data.SceneGroup;
|
||||
import org.anime_game_servers.gi_lua.models.scene.group.SceneGroup;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
@ -6,7 +6,7 @@ import emu.grasscutter.game.dungeons.challenge.WorldChallenge;
|
||||
import emu.grasscutter.game.dungeons.challenge.enums.ChallengeType;
|
||||
import emu.grasscutter.game.dungeons.challenge.trigger.TriggerGroupTriggerTrigger;
|
||||
import emu.grasscutter.game.world.Scene;
|
||||
import emu.grasscutter.scripts.data.SceneGroup;
|
||||
import org.anime_game_servers.gi_lua.models.scene.group.SceneGroup;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
@ -7,7 +7,7 @@ import emu.grasscutter.game.dungeons.challenge.enums.ChallengeType;
|
||||
import emu.grasscutter.game.dungeons.challenge.trigger.TimeTrigger;
|
||||
import emu.grasscutter.game.dungeons.challenge.trigger.TriggerGroupTriggerTrigger;
|
||||
import emu.grasscutter.game.world.Scene;
|
||||
import emu.grasscutter.scripts.data.SceneGroup;
|
||||
import org.anime_game_servers.gi_lua.models.scene.group.SceneGroup;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
@ -8,7 +8,7 @@ import emu.grasscutter.game.dungeons.challenge.trigger.KillMonsterTrigger;
|
||||
import emu.grasscutter.game.dungeons.challenge.trigger.TimeTrigger;
|
||||
import emu.grasscutter.game.dungeons.challenge.trigger.TriggerGroupTriggerTrigger;
|
||||
import emu.grasscutter.game.world.Scene;
|
||||
import emu.grasscutter.scripts.data.SceneGroup;
|
||||
import org.anime_game_servers.gi_lua.models.scene.group.SceneGroup;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
@ -5,9 +5,9 @@ import emu.grasscutter.game.entity.EntityGadget;
|
||||
import emu.grasscutter.game.entity.EntityMonster;
|
||||
import emu.grasscutter.game.entity.GameEntity;
|
||||
import emu.grasscutter.game.props.ElementReactionType;
|
||||
import emu.grasscutter.scripts.data.SceneTrigger;
|
||||
import emu.grasscutter.server.packet.send.PacketChallengeDataNotify;
|
||||
import lombok.Getter;
|
||||
import org.anime_game_servers.gi_lua.models.scene.group.SceneTrigger;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
package emu.grasscutter.game.dungeons.challenge.trigger;
|
||||
|
||||
import emu.grasscutter.game.dungeons.challenge.WorldChallenge;
|
||||
import emu.grasscutter.scripts.data.SceneTrigger;
|
||||
import org.anime_game_servers.gi_lua.models.scene.group.SceneTrigger;
|
||||
|
||||
public class TriggerGroupTriggerTrigger extends ChallengeTrigger{
|
||||
private final String TRIGGER_TAG;
|
||||
|
@ -12,12 +12,12 @@ import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.game.quest.GameMainQuest;
|
||||
import emu.grasscutter.game.quest.GameQuest;
|
||||
import emu.grasscutter.game.quest.enums.QuestContent;
|
||||
import emu.grasscutter.game.quest.enums.QuestState;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import lombok.NonNull;
|
||||
import lombok.val;
|
||||
import messages.dungeon.DungeonEntryInfo;
|
||||
import messages.scene.entity.WeeklyBossResinDiscountInfo;
|
||||
import org.anime_game_servers.core.gi.enums.QuestState;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Stream;
|
||||
|
@ -1,7 +1,7 @@
|
||||
package emu.grasscutter.game.dungeons.enums;
|
||||
|
||||
import emu.grasscutter.scripts.constants.IntValueEnum;
|
||||
import lombok.Getter;
|
||||
import org.anime_game_servers.core.base.interfaces.IntValueEnum;
|
||||
|
||||
public enum DungeonPassConditionType implements IntValueEnum {
|
||||
DUNGEON_COND_NONE(0),
|
||||
|
@ -4,12 +4,12 @@ import emu.grasscutter.data.binout.config.ConfigEntityGadget;
|
||||
import emu.grasscutter.game.props.FightProperty;
|
||||
import emu.grasscutter.game.quest.enums.QuestContent;
|
||||
import emu.grasscutter.game.world.Scene;
|
||||
import emu.grasscutter.scripts.data.ScriptArgs;
|
||||
import emu.grasscutter.server.event.entity.EntityDamageEvent;
|
||||
import emu.grasscutter.utils.Position;
|
||||
import lombok.Getter;
|
||||
import org.anime_game_servers.gi_lua.models.ScriptArgs;
|
||||
|
||||
import static emu.grasscutter.scripts.constants.EventType.EVENT_SPECIFIC_GADGET_HP_CHANGE;
|
||||
import static org.anime_game_servers.gi_lua.models.constants.EventType.EVENT_SPECIFIC_GADGET_HP_CHANGE;
|
||||
|
||||
public abstract class EntityBaseGadget extends GameEntity {
|
||||
@Getter(onMethod = @__(@Override))
|
||||
|
@ -1,8 +1,6 @@
|
||||
package emu.grasscutter.game.entity;
|
||||
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.data.GameData;
|
||||
import emu.grasscutter.data.binout.AbilityData;
|
||||
import emu.grasscutter.data.binout.config.ConfigEntityGadget;
|
||||
import emu.grasscutter.data.binout.config.fields.ConfigAbilityData;
|
||||
import emu.grasscutter.data.excels.GadgetData;
|
||||
|
@ -16,9 +16,6 @@ import emu.grasscutter.game.world.Scene;
|
||||
import emu.grasscutter.game.world.SceneGroupInstance;
|
||||
import emu.grasscutter.net.proto.VisionTypeOuterClass;
|
||||
import emu.grasscutter.scripts.EntityControllerScriptManager;
|
||||
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.server.packet.send.PacketPlatformStartRouteNotify;
|
||||
import emu.grasscutter.server.packet.send.PacketPlatformStopRouteNotify;
|
||||
@ -34,6 +31,9 @@ import lombok.val;
|
||||
import messages.gadget.GadgetInteractReq;
|
||||
import messages.general.ability.AbilitySyncStateInfo;
|
||||
import messages.scene.entity.*;
|
||||
import org.anime_game_servers.gi_lua.models.ScriptArgs;
|
||||
import org.anime_game_servers.gi_lua.models.constants.EventType;
|
||||
import org.anime_game_servers.gi_lua.models.scene.group.SceneGadget;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.ArrayList;
|
||||
@ -126,8 +126,8 @@ public class EntityGadget extends EntityBaseGadget implements ConfigAbilityDataA
|
||||
public void setState(int state) {
|
||||
this.state = state;
|
||||
//Cache the gadget state
|
||||
if(metaGadget != null && metaGadget.getGroup() != null) {
|
||||
var instance = getScene().getScriptManager().getCachedGroupInstanceById(metaGadget.getGroup().getId());
|
||||
if(metaGadget != null && metaGadget.getGroupId() > 0) {
|
||||
var instance = getScene().getScriptManager().getCachedGroupInstanceById(metaGadget.getGroupId());
|
||||
if(instance != null) instance.cacheGadgetState(metaGadget, state);
|
||||
}
|
||||
}
|
||||
@ -207,7 +207,7 @@ public class EntityGadget extends EntityBaseGadget implements ConfigAbilityDataA
|
||||
|
||||
SceneGroupInstance groupInstance = getScene().getScriptManager().getCachedGroupInstanceById(this.getGroupId());
|
||||
if(groupInstance != null && metaGadget != null)
|
||||
groupInstance.getDeadEntities().add(metaGadget.getConfig_id());
|
||||
groupInstance.getDeadEntities().add(metaGadget.getConfigId());
|
||||
|
||||
val hostBlossom = getScene().getWorld().getHost().getBlossomManager();
|
||||
val removedChest = hostBlossom.getSpawnedChest().remove(getConfigId());
|
||||
@ -278,7 +278,7 @@ public class EntityGadget extends EntityBaseGadget implements ConfigAbilityDataA
|
||||
gadgetInfo.setAuthorityPeerId(this.getScene().getWorld().getHostPeerId());
|
||||
|
||||
if (this.metaGadget != null) {
|
||||
gadgetInfo.setDraftId(this.metaGadget.getDraft_id());
|
||||
gadgetInfo.setDraftId(this.metaGadget.getDraftId());
|
||||
}
|
||||
|
||||
if(owner != null){
|
||||
|
@ -1,7 +1,6 @@
|
||||
package emu.grasscutter.game.entity;
|
||||
|
||||
import emu.grasscutter.data.GameData;
|
||||
import emu.grasscutter.data.binout.AbilityData;
|
||||
import emu.grasscutter.data.binout.config.ConfigEntityMonster;
|
||||
import emu.grasscutter.data.binout.config.fields.ConfigAbilityData;
|
||||
import emu.grasscutter.data.common.PropGrowCurve;
|
||||
@ -11,17 +10,12 @@ import emu.grasscutter.data.excels.MonsterCurveData;
|
||||
import emu.grasscutter.data.excels.MonsterData;
|
||||
import emu.grasscutter.game.ability.AbilityManager;
|
||||
import emu.grasscutter.game.dungeons.enums.DungeonPassConditionType;
|
||||
import emu.grasscutter.game.entity.interfaces.ConfigAbilityDataAbilityEntity;
|
||||
import emu.grasscutter.game.entity.interfaces.StringAbilityEntity;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.game.props.*;
|
||||
import emu.grasscutter.game.quest.enums.QuestContent;
|
||||
import emu.grasscutter.game.world.Scene;
|
||||
import emu.grasscutter.game.world.SceneGroupInstance;
|
||||
import emu.grasscutter.scripts.constants.EventType;
|
||||
import emu.grasscutter.scripts.data.SceneGroup;
|
||||
import emu.grasscutter.scripts.data.SceneMonster;
|
||||
import emu.grasscutter.scripts.data.ScriptArgs;
|
||||
import emu.grasscutter.server.event.entity.EntityDamageEvent;
|
||||
import emu.grasscutter.utils.Position;
|
||||
import emu.grasscutter.utils.ProtoHelper;
|
||||
@ -34,12 +28,16 @@ import messages.gadget.GadgetInteractReq;
|
||||
import messages.general.ability.AbilitySyncStateInfo;
|
||||
import messages.general.entity.SceneWeaponInfo;
|
||||
import messages.scene.entity.*;
|
||||
import org.anime_game_servers.gi_lua.models.ScriptArgs;
|
||||
import org.anime_game_servers.gi_lua.models.constants.EventType;
|
||||
import org.anime_game_servers.gi_lua.models.scene.group.SceneGroup;
|
||||
import org.anime_game_servers.gi_lua.models.scene.group.SceneMonster;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static emu.grasscutter.scripts.constants.EventType.EVENT_SPECIFIC_MONSTER_HP_CHANGE;
|
||||
import static org.anime_game_servers.gi_lua.models.constants.EventType.EVENT_SPECIFIC_MONSTER_HP_CHANGE;
|
||||
|
||||
public class EntityMonster extends GameEntity implements StringAbilityEntity {
|
||||
@Getter(onMethod = @__(@Override))
|
||||
@ -123,7 +121,7 @@ public class EntityMonster extends GameEntity implements StringAbilityEntity {
|
||||
ArrayList<String> abilityNames = new ArrayList<>();
|
||||
val defaultAbilities = GameData.getConfigGlobalCombat().getDefaultAbilities();
|
||||
//Affix abilities
|
||||
Optional<SceneGroup> optionalGroup = getScene().getLoadedGroups().stream().filter(g -> g.getId() == getGroupId()).findAny();
|
||||
Optional<SceneGroup> optionalGroup = getScene().getLoadedGroups().stream().filter(g -> g.getGroupInfo().getId() == getGroupId()).findAny();
|
||||
List<MonsterAffixData> affixes = getAffixes(optionalGroup.orElse(null));
|
||||
|
||||
// first add pre add affix abilities
|
||||
@ -277,7 +275,7 @@ public class EntityMonster extends GameEntity implements StringAbilityEntity {
|
||||
|
||||
SceneGroupInstance groupInstance = scene.getScriptManager().getGroupInstanceById(this.getGroupId());
|
||||
if(groupInstance != null && metaMonster != null)
|
||||
groupInstance.getDeadEntities().add(metaMonster.getConfig_id());
|
||||
groupInstance.getDeadEntities().add(metaMonster.getConfigId());
|
||||
|
||||
scene.triggerDungeonEvent(DungeonPassConditionType.DUNGEON_COND_KILL_GROUP_MONSTER, this.getGroupId());
|
||||
scene.triggerDungeonEvent(DungeonPassConditionType.DUNGEON_COND_KILL_TYPE_MONSTER, this.getMonsterData().getType().getValue());
|
||||
@ -341,9 +339,9 @@ public class EntityMonster extends GameEntity implements StringAbilityEntity {
|
||||
monsterInfo.setBlockId(getScene().getId());
|
||||
monsterInfo.setBornType(MonsterBornType.MONSTER_BORN_DEFAULT);
|
||||
|
||||
if(metaMonster!=null && metaMonster.getSpecial_name_id()!=0){
|
||||
monsterInfo.setTitleId(this.metaMonster.getTitle_id());
|
||||
monsterInfo.setSpecialNameId(this.metaMonster.getSpecial_name_id());
|
||||
if(metaMonster!=null && metaMonster.getSpecialNameId()!=0){
|
||||
monsterInfo.setTitleId(this.metaMonster.getTitleId());
|
||||
monsterInfo.setSpecialNameId(this.metaMonster.getSpecialNameId());
|
||||
} else if (monsterData.getDescribeData() != null) {
|
||||
monsterInfo.setTitleId(monsterData.getDescribeData().getTitleId());
|
||||
monsterInfo.setSpecialNameId(monsterData.getSpecialNameId());
|
||||
|
@ -2,8 +2,6 @@ package emu.grasscutter.game.entity;
|
||||
|
||||
import emu.grasscutter.game.props.EntityIdType;
|
||||
import emu.grasscutter.game.world.Scene;
|
||||
import emu.grasscutter.net.proto.*;
|
||||
import emu.grasscutter.scripts.data.SceneNPC;
|
||||
import emu.grasscutter.utils.Position;
|
||||
import it.unimi.dsi.fastutil.ints.Int2FloatMap;
|
||||
import lombok.Getter;
|
||||
@ -11,6 +9,7 @@ import lombok.val;
|
||||
import messages.general.Vector;
|
||||
import messages.general.ability.AbilitySyncStateInfo;
|
||||
import messages.scene.entity.*;
|
||||
import org.anime_game_servers.gi_lua.models.scene.group.SceneNPC;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ -25,12 +24,12 @@ public class EntityNPC extends GameEntity {
|
||||
public EntityNPC(Scene scene, SceneNPC metaNPC, int blockId, int suiteId) {
|
||||
super(scene);
|
||||
this.id = getScene().getWorld().getNextEntityId(EntityIdType.NPC);
|
||||
setConfigId(metaNPC.getConfig_id());
|
||||
setGroupId(metaNPC.getGroup().getId());
|
||||
setConfigId(metaNPC.getConfigId());
|
||||
setGroupId(metaNPC.getGroupId());
|
||||
setBlockId(blockId);
|
||||
this.suiteId = suiteId;
|
||||
this.position = metaNPC.getPos().clone();
|
||||
this.rotation = metaNPC.getRot().clone();
|
||||
this.position = new Position(metaNPC.getPos());
|
||||
this.rotation = new Position(metaNPC.getRot());
|
||||
this.metaNpc = metaNPC;
|
||||
|
||||
}
|
||||
|
@ -2,11 +2,11 @@ package emu.grasscutter.game.entity;
|
||||
|
||||
import emu.grasscutter.game.props.EntityIdType;
|
||||
import emu.grasscutter.game.world.Scene;
|
||||
import emu.grasscutter.scripts.data.SceneRegion;
|
||||
import emu.grasscutter.utils.Position;
|
||||
import it.unimi.dsi.fastutil.ints.Int2FloatMap;
|
||||
import lombok.Getter;
|
||||
import messages.scene.entity.SceneEntityInfo;
|
||||
import org.anime_game_servers.gi_lua.models.scene.group.SceneRegion;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
@ -24,10 +24,10 @@ public class EntityRegion extends GameEntity{
|
||||
public EntityRegion(Scene scene, SceneRegion region) {
|
||||
super(scene);
|
||||
this.id = getScene().getWorld().getNextEntityId(EntityIdType.REGION);
|
||||
setGroupId(region.getGroup().getId());
|
||||
setBlockId(region.getGroup().block_id);
|
||||
setConfigId(region.getConfig_id());
|
||||
this.position = region.getPos().clone();
|
||||
setGroupId(region.getGroupId());
|
||||
setBlockId(region.getBlockId());
|
||||
setConfigId(region.getConfigId());
|
||||
this.position = new Position(region.getPos());
|
||||
this.entities = ConcurrentHashMap.newKeySet();
|
||||
this.newEntities = ConcurrentHashMap.newKeySet();
|
||||
this.leftEntities = ConcurrentHashMap.newKeySet();
|
||||
@ -45,7 +45,7 @@ public class EntityRegion extends GameEntity{
|
||||
|
||||
@Override
|
||||
public int getEntityTypeId() {
|
||||
return metaRegion.getConfig_id();
|
||||
return metaRegion.getConfigId();
|
||||
}
|
||||
|
||||
public boolean hasNewEntities() {
|
||||
|
@ -1,11 +1,9 @@
|
||||
package emu.grasscutter.game.entity.gadget;
|
||||
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.game.dungeons.DungeonManager;
|
||||
import emu.grasscutter.game.entity.EntityGadget;
|
||||
import emu.grasscutter.game.entity.gadget.chest.BossChestInteractHandler;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.scripts.constants.ScriptGadgetState;
|
||||
import emu.grasscutter.server.packet.send.PacketGadgetInteractRsp;
|
||||
import lombok.val;
|
||||
import messages.gadget.GadgetInteractReq;
|
||||
@ -14,6 +12,8 @@ import messages.gadget.InteractType;
|
||||
import messages.gadget.ResinCostType;
|
||||
import messages.scene.entity.BossChestInfo;
|
||||
import messages.scene.entity.SceneGadgetInfo;
|
||||
import org.anime_game_servers.gi_lua.models.constants.ScriptGadgetState;
|
||||
import org.anime_game_servers.gi_lua.models.scene.group.SceneGadget;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
@ -60,9 +60,9 @@ public class GadgetChest extends GadgetContent {
|
||||
val playersUid = getGadget().getScene().getPlayers().stream().map(Player::getUid).toList();
|
||||
|
||||
Optional.ofNullable(getGadget().getMetaGadget())
|
||||
.map(g -> g.getBoss_chest())
|
||||
.map(SceneGadget::getBossChest)
|
||||
.ifPresent(bossChest -> {
|
||||
val chestProto = new BossChestInfo(bossChest.getMonster_config_id(), bossChest.getResin());
|
||||
val chestProto = new BossChestInfo(bossChest.getMonsterConfigId(), bossChest.getResin());
|
||||
|
||||
// removing instead of creating new list directly below is because
|
||||
// it also has to consider normal cases
|
||||
|
@ -30,16 +30,22 @@ public class BossChestInteractHandler implements ChestInteractHandler{
|
||||
|
||||
val worldDataManager = chest.getGadget().getScene().getWorld().getServer().getWorldDataSystem();
|
||||
val chestMetaGadget = chest.getGadget().getMetaGadget();
|
||||
val monsterCfgId = chestMetaGadget.getBoss_chest().getMonster_config_id();
|
||||
val groupMonsters = chestMetaGadget.getGroup().getMonsters();
|
||||
val group = chestMetaGadget.getSceneMeta().getGroup(chestMetaGadget.getGroupId());
|
||||
if(group == null){
|
||||
Grasscutter.getLogger().warn("group is null {} unable to get cfg id {}",
|
||||
chestMetaGadget.getGroupId(), chestMetaGadget.getBossChest().getMonsterConfigId());
|
||||
return false;
|
||||
}
|
||||
val monsterCfgId = chestMetaGadget.getBossChest().getMonsterConfigId();
|
||||
val groupMonsters = group.getMonsters();
|
||||
if(groupMonsters == null){
|
||||
Grasscutter.getLogger().warn("group monsters are null {} unable to get cfg id {}",
|
||||
chestMetaGadget.getGroup().getId(), monsterCfgId);
|
||||
chestMetaGadget.getGroupId(), monsterCfgId);
|
||||
return false;
|
||||
}
|
||||
val monster = groupMonsters.get(monsterCfgId);
|
||||
|
||||
val reward = worldDataManager.getRewardByBossId(monster.getMonster_id());
|
||||
val reward = worldDataManager.getRewardByBossId(monster.getMonsterId());
|
||||
|
||||
if (reward == null) {
|
||||
val dungeonManager = player.getScene().getDungeonManager();
|
||||
@ -47,7 +53,7 @@ public class BossChestInteractHandler implements ChestInteractHandler{
|
||||
if(dungeonManager != null){
|
||||
return dungeonManager.getStatueDrops(player, useCondensedResin, chest.getGadget().getGroupId());
|
||||
}
|
||||
Grasscutter.getLogger().warn("Could not found the reward of boss monster {}", monster.getMonster_id());
|
||||
Grasscutter.getLogger().warn("Could not found the reward of boss monster {}", monster.getMonsterId());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1,13 +1,13 @@
|
||||
package emu.grasscutter.game.entity.gadget.platform;
|
||||
|
||||
import emu.grasscutter.game.world.Scene;
|
||||
import emu.grasscutter.scripts.data.SceneGadget;
|
||||
import emu.grasscutter.utils.Position;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.val;
|
||||
import messages.general.MathQuaternion;
|
||||
import messages.scene.entity.PlatformInfo;
|
||||
import org.anime_game_servers.gi_lua.models.scene.group.SceneGadget;
|
||||
|
||||
public abstract class BaseRoute {
|
||||
@Getter @Setter private boolean isStarted;
|
||||
@ -24,14 +24,14 @@ public abstract class BaseRoute {
|
||||
|
||||
BaseRoute(SceneGadget gadget) {
|
||||
this.startRot = new Position(gadget.getRot());
|
||||
this.isStarted = gadget.isStart_route();
|
||||
this.isActive = gadget.isStart_route();
|
||||
this.isStarted = gadget.isStartRoute();
|
||||
this.isActive = gadget.isStartRoute();
|
||||
}
|
||||
|
||||
public static BaseRoute fromSceneGadget(SceneGadget sceneGadget) {
|
||||
if (sceneGadget.getRoute_id() != 0) {
|
||||
if (sceneGadget.getRouteId() != 0) {
|
||||
return new ConfigRoute(sceneGadget);
|
||||
} else if (sceneGadget.is_use_point_array()) {
|
||||
} else if (sceneGadget.isUsePointArray()) {
|
||||
return new PointArrayRoute(sceneGadget);
|
||||
}
|
||||
return null;
|
||||
|
@ -1,12 +1,12 @@
|
||||
package emu.grasscutter.game.entity.gadget.platform;
|
||||
|
||||
import emu.grasscutter.scripts.data.SceneGadget;
|
||||
import emu.grasscutter.utils.Position;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.val;
|
||||
import messages.scene.entity.MovingPlatformType;
|
||||
import messages.scene.entity.PlatformInfo;
|
||||
import org.anime_game_servers.gi_lua.models.scene.group.SceneGadget;
|
||||
|
||||
public class ConfigRoute extends BaseRoute {
|
||||
|
||||
@ -14,7 +14,7 @@ public class ConfigRoute extends BaseRoute {
|
||||
|
||||
public ConfigRoute(SceneGadget gadget) {
|
||||
super(gadget);
|
||||
this.routeId = gadget.getRoute_id();
|
||||
this.routeId = gadget.getRouteId();
|
||||
}
|
||||
|
||||
public ConfigRoute(Position startRot, boolean startRoute, boolean isActive, int routeId) {
|
||||
|
@ -1,12 +1,12 @@
|
||||
package emu.grasscutter.game.entity.gadget.platform;
|
||||
|
||||
import emu.grasscutter.scripts.data.SceneGadget;
|
||||
import emu.grasscutter.utils.Position;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.val;
|
||||
import messages.scene.entity.MovingPlatformType;
|
||||
import messages.scene.entity.PlatformInfo;
|
||||
import org.anime_game_servers.gi_lua.models.scene.group.SceneGadget;
|
||||
|
||||
/**
|
||||
* TODO implement point array routes, read from missing resources
|
||||
|
@ -6,6 +6,7 @@ import java.util.stream.IntStream;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import dev.morphia.annotations.Entity;
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.data.GameData;
|
||||
import emu.grasscutter.data.excels.*;
|
||||
import emu.grasscutter.data.excels.BlossomRefreshData.*;
|
||||
@ -16,8 +17,6 @@ import emu.grasscutter.game.player.BasePlayerDataManager;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.game.props.ActionReason;
|
||||
import emu.grasscutter.net.proto.BlossomBriefInfoOuterClass;
|
||||
import emu.grasscutter.scripts.constants.EventType;
|
||||
import emu.grasscutter.scripts.data.ScriptArgs;
|
||||
import emu.grasscutter.server.packet.send.PacketBlossomBriefInfoNotify;
|
||||
import emu.grasscutter.server.packet.send.PacketWorldOwnerBlossomScheduleInfoNotify;
|
||||
import emu.grasscutter.utils.Utils;
|
||||
@ -25,6 +24,8 @@ import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import lombok.val;
|
||||
import messages.gadget.BlossomChestInfo;
|
||||
import org.anime_game_servers.gi_lua.models.ScriptArgs;
|
||||
import org.anime_game_servers.gi_lua.models.constants.EventType;
|
||||
|
||||
@Getter
|
||||
@Entity
|
||||
@ -174,6 +175,7 @@ public class BlossomManager extends BasePlayerDataManager {
|
||||
public void buildNextCamp(int groupId) {
|
||||
val schedule = this.blossomSchedule.remove(groupId);
|
||||
if(schedule == null) return;
|
||||
val world = player.getWorld();
|
||||
|
||||
Optional.ofNullable(GameData.getBlossomGroupsDataMap().get(schedule.getCircleCampId()))
|
||||
.map(BlossomGroupsData::getNextCampId)
|
||||
@ -181,14 +183,20 @@ public class BlossomManager extends BasePlayerDataManager {
|
||||
// if next camp overlaps with existing schedule, get further next camp
|
||||
.map(groupsData -> this.blossomSchedule.containsKey(groupsData.getNewGroupId()) ?
|
||||
GameData.getBlossomGroupsDataMap().get(groupsData.getNextCampId()) : groupsData).stream()
|
||||
.map(groupData -> BlossomSchedule.create(schedule, groupData, getWorldLevel()))
|
||||
.map(groupData -> BlossomSchedule.create(world, schedule, groupData, getWorldLevel()))
|
||||
.filter(Objects::nonNull)
|
||||
.peek(newSchedule -> this.blossomSchedule.put(newSchedule.getGroupId(), newSchedule))
|
||||
.peek(newSchedule -> this.player.getScene().runWhenFinished(() -> this.player.getScene().loadDynamicGroup(newSchedule.getGroupId())))
|
||||
// .peek(newSchedule -> Grasscutter.getLogger().info("[BlossomManager] New {}", newSchedule))
|
||||
.map(BlossomSchedule::getDecorateGroupId)
|
||||
.forEach(decorateGroupId -> this.player.getScene().runWhenFinished(() -> this.player.getScene().loadDynamicGroup(decorateGroupId)));
|
||||
// .forEach(decorateId -> Grasscutter.getLogger().info("[BlossomManager] New Decorate Group: {}", decorateId));
|
||||
.forEach(newSchedule -> {
|
||||
this.blossomSchedule.put(newSchedule.getGroupId(), newSchedule);
|
||||
this.player.getScene().runWhenFinished(() -> {
|
||||
this.player.getScene().loadDynamicGroup(newSchedule.getGroupId());
|
||||
val decorateGroupId = newSchedule.getDecorateGroupId();
|
||||
if(decorateGroupId != 0) {
|
||||
Grasscutter.getLogger().debug("[BlossomManager] New Decorate Group: {}", decorateGroupId);
|
||||
this.player.getScene().loadDynamicGroup(decorateGroupId);
|
||||
}
|
||||
});
|
||||
});
|
||||
notifyPlayerIcon(); // notify all camps again
|
||||
}
|
||||
|
||||
@ -196,13 +204,20 @@ public class BlossomManager extends BasePlayerDataManager {
|
||||
* Rebuild all Blossom Camp gadget (not chest gadget) for scene
|
||||
* */
|
||||
public void loadBlossomGroup() {
|
||||
Optional.ofNullable(this.player.getScene()).ifPresent(scene -> this.blossomSchedule.values().stream()
|
||||
val scene = this.player.getScene();
|
||||
if (scene == null) return;
|
||||
|
||||
this.blossomSchedule.values().stream()
|
||||
.filter(schedule -> schedule.getSceneId() == scene.getId())
|
||||
.peek(schedule -> scene.loadDynamicGroup(schedule.getGroupId()))
|
||||
.forEach(schedule -> {
|
||||
scene.loadDynamicGroup(schedule.getGroupId());
|
||||
val decorateGroupId = schedule.getDecorateGroupId();
|
||||
if(decorateGroupId != 0) {
|
||||
Grasscutter.getLogger().debug("[BlossomManager] Decorate Group: {}", decorateGroupId);
|
||||
scene.loadDynamicGroup(decorateGroupId);
|
||||
}
|
||||
});
|
||||
// .peek(schedule -> Grasscutter.getLogger().info("[Blossom Manager] Loading Blossom Group: {}", schedule.getGroupId()))
|
||||
.map(BlossomSchedule::getDecorateGroupId)
|
||||
.forEach(scene::loadDynamicGroup));
|
||||
// .forEach(decorateId -> Grasscutter.getLogger().info("[Blossom Manager] Loading Decorate Group:{}", decorateId)));
|
||||
}
|
||||
|
||||
private int getWorldLevel() {
|
||||
@ -266,7 +281,7 @@ public class BlossomManager extends BasePlayerDataManager {
|
||||
.map(sectionList -> IntStream.range(0, data.getRefreshCount()).mapToObj(e ->
|
||||
Stream.ofNullable(groupList).filter(gl -> !gl.isEmpty()).map(Utils::drawRandomListElement)// draw a new random group
|
||||
.peek(randomGroup -> appendedGroupId.add(randomGroup.getId())).peek(groupList::remove)
|
||||
.map(randomGroup -> BlossomSchedule.create(data, randomGroup, getWorldLevel())) // build blossom schedule
|
||||
.map(randomGroup -> BlossomSchedule.create(player.getWorld(), data, randomGroup, getWorldLevel())) // build blossom schedule
|
||||
.filter(Objects::nonNull).findFirst().orElse(null))
|
||||
.filter(Objects::nonNull).toList())
|
||||
.findFirst().orElse(null);
|
||||
|
@ -2,17 +2,22 @@ package emu.grasscutter.game.managers.blossom;
|
||||
|
||||
import dev.morphia.annotations.Entity;
|
||||
import emu.grasscutter.GameConstants;
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.data.GameData;
|
||||
import emu.grasscutter.data.common.BaseBlossomROSData;
|
||||
import emu.grasscutter.data.excels.*;
|
||||
import emu.grasscutter.game.managers.blossom.enums.BlossomRefreshType;
|
||||
import emu.grasscutter.game.world.World;
|
||||
import emu.grasscutter.net.proto.BlossomBriefInfoOuterClass.BlossomBriefInfo;
|
||||
import emu.grasscutter.net.proto.BlossomScheduleInfoOuterClass.BlossomScheduleInfo;
|
||||
import emu.grasscutter.scripts.data.SceneGroup;
|
||||
import emu.grasscutter.scripts.ScriptSystem;
|
||||
import emu.grasscutter.utils.Position;
|
||||
import lombok.*;
|
||||
import org.anime_game_servers.gi_lua.models.scene.group.SceneGroup;
|
||||
import org.anime_game_servers.core.gi.models.Vector;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.time.LocalTime;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.*;
|
||||
@ -48,19 +53,30 @@ public class BlossomSchedule implements BaseBlossomROSData {
|
||||
/**
|
||||
* Builder function
|
||||
* */
|
||||
public static BlossomSchedule create(@NotNull BaseBlossomROSData baseData, @NotNull BlossomGroupsData groupsData, int worldLevel) {
|
||||
public static BlossomSchedule create(@Nonnull World world, @NotNull BaseBlossomROSData baseData, @NotNull BlossomGroupsData groupsData, int worldLevel) {
|
||||
final int sceneId = Optional.ofNullable(GameData.getCityDataMap().get(groupsData.getCityId())).map(CityData::getSceneId)
|
||||
.orElse(3);
|
||||
val scriptSystem = world.getHost().getServer().getScriptSystem();
|
||||
val scene = scriptSystem.getSceneMeta(sceneId);
|
||||
|
||||
return Optional.ofNullable(SceneGroup.of(groupsData.getNewGroupId()).load(sceneId))
|
||||
.map(SceneGroup::getGadgets)
|
||||
.map(Map::values)
|
||||
.stream().flatMap(Collection::stream)
|
||||
.filter(gadget -> gadget.getGadget_id() == baseData.getRefreshType().getGadgetId())
|
||||
val group = scene.getGroup(groupsData.getNewGroupId());
|
||||
if(group == null) {
|
||||
Grasscutter.getLogger().warn("[BlossomSchedule] Unable to find group {} in scene {}", groupsData.getNewGroupId(), sceneId);
|
||||
return null;
|
||||
}
|
||||
|
||||
group.load(ScriptSystem.getScriptLoader());
|
||||
val gadgets = group.getGadgets();
|
||||
if(gadgets == null || gadgets.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return gadgets.values().stream()
|
||||
.filter(gadget -> gadget.getGadgetId() == baseData.getRefreshType().getGadgetId())
|
||||
.map(gadget -> BlossomSchedule.of()
|
||||
.setSceneId(sceneId)
|
||||
.setCityId(baseData.getCityId())
|
||||
.setPosition(gadget.getPos())
|
||||
.setPosition(new Position(gadget.getPos()))
|
||||
.setResin(getResinCost(baseData.getRefreshType()))
|
||||
.setMonsterLevel(getMonsterLevel(worldLevel))
|
||||
.setRewardId(baseData.getRewardId(worldLevel))
|
||||
|
@ -60,7 +60,6 @@ import emu.grasscutter.net.proto.CombatInvokeEntryOuterClass.CombatInvokeEntry;
|
||||
import emu.grasscutter.net.proto.PlayerApplyEnterMpResultNotifyOuterClass;
|
||||
import emu.grasscutter.net.proto.PropChangeReasonOuterClass.PropChangeReason;
|
||||
import emu.grasscutter.net.proto.TrialAvatarGrantRecordOuterClass.TrialAvatarGrantRecord.GrantReason;
|
||||
import emu.grasscutter.scripts.data.SceneRegion;
|
||||
import emu.grasscutter.server.event.player.PlayerJoinEvent;
|
||||
import emu.grasscutter.server.event.player.PlayerQuitEvent;
|
||||
import emu.grasscutter.server.game.GameServer;
|
||||
|
@ -8,20 +8,20 @@ import emu.grasscutter.game.props.ActionReason;
|
||||
import emu.grasscutter.game.quest.enums.ParentQuestState;
|
||||
import emu.grasscutter.game.quest.enums.QuestCond;
|
||||
import emu.grasscutter.game.quest.enums.QuestContent;
|
||||
import emu.grasscutter.game.quest.enums.QuestState;
|
||||
import emu.grasscutter.net.proto.RetcodeOuterClass.Retcode;
|
||||
import emu.grasscutter.scripts.data.ScriptArgs;
|
||||
import emu.grasscutter.server.packet.send.PacketOpenStateChangeNotify;
|
||||
import emu.grasscutter.server.packet.send.PacketOpenStateUpdateNotify;
|
||||
import emu.grasscutter.server.packet.send.PacketSceneAreaUnlockNotify;
|
||||
import emu.grasscutter.server.packet.send.PacketScenePointUnlockNotify;
|
||||
import emu.grasscutter.server.packet.send.PacketSetOpenStateRsp;
|
||||
import lombok.val;
|
||||
import org.anime_game_servers.core.gi.enums.QuestState;
|
||||
import org.anime_game_servers.gi_lua.models.ScriptArgs;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static emu.grasscutter.scripts.constants.EventType.EVENT_UNLOCK_TRANS_POINT;
|
||||
import static org.anime_game_servers.gi_lua.models.constants.EventType.EVENT_UNLOCK_TRANS_POINT;
|
||||
|
||||
// @Entity
|
||||
public class PlayerProgressManager extends BasePlayerDataManager {
|
||||
|
@ -15,6 +15,7 @@ public enum ActivityType {
|
||||
NONE(0),
|
||||
NEW_ACTIVITY_TRIAL_AVATAR(4),
|
||||
NEW_ACTIVITY_PERSONAL_LIINE(8),
|
||||
NEW_ACTIVITY_ASTER(1100),
|
||||
NEW_ACTIVITY_SALESMAN_MP(1205),
|
||||
NEW_ACTIVITY_SUMMER_TIME(1600),
|
||||
NEW_ACTIVITY_GENERAL_BANNER(2100),
|
||||
|
@ -4,11 +4,11 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import emu.grasscutter.scripts.constants.IntValueEnum;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import org.anime_game_servers.core.base.interfaces.IntValueEnum;
|
||||
|
||||
public enum CampTargetType implements IntValueEnum{
|
||||
public enum CampTargetType implements IntValueEnum {
|
||||
None (0),
|
||||
Alliance (1),
|
||||
Enemy (2),
|
||||
|
@ -4,11 +4,11 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import emu.grasscutter.scripts.constants.IntValueEnum;
|
||||
import emu.grasscutter.utils.Utils;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import lombok.Getter;
|
||||
import org.anime_game_servers.core.base.interfaces.IntValueEnum;
|
||||
|
||||
public enum ElementType implements IntValueEnum {
|
||||
None (0, FightProperty.FIGHT_PROP_CUR_FIRE_ENERGY, FightProperty.FIGHT_PROP_MAX_FIRE_ENERGY),
|
||||
|
@ -4,13 +4,13 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import emu.grasscutter.scripts.constants.IntValueEnum;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import lombok.Getter;
|
||||
import org.anime_game_servers.core.base.interfaces.IntValueEnum;
|
||||
|
||||
|
||||
public enum EntityType implements IntValueEnum{
|
||||
public enum EntityType implements IntValueEnum {
|
||||
None (0),
|
||||
Avatar (1),
|
||||
Monster (2),
|
||||
|
@ -14,6 +14,7 @@ import java.util.stream.Stream;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import lombok.Getter;
|
||||
import org.anime_game_servers.core.gi.enums.Element;
|
||||
|
||||
public enum FightProperty {
|
||||
FIGHT_PROP_NONE(0),
|
||||
@ -231,4 +232,31 @@ public enum FightProperty {
|
||||
public static boolean isPercentage(FightProperty prop) {
|
||||
return !flatProps.contains(prop);
|
||||
}
|
||||
|
||||
public static FightProperty getCurrentEnergyProp(Element element){
|
||||
return switch (element){
|
||||
case FIRE -> FIGHT_PROP_CUR_FIRE_ENERGY;
|
||||
case WATER -> FIGHT_PROP_CUR_WATER_ENERGY;
|
||||
case GRASS -> FIGHT_PROP_CUR_GRASS_ENERGY;
|
||||
case ELECTRIC -> FIGHT_PROP_CUR_ELEC_ENERGY;
|
||||
case ICE -> FIGHT_PROP_CUR_ICE_ENERGY;
|
||||
case WIND -> FIGHT_PROP_CUR_WIND_ENERGY;
|
||||
case ROCK -> FIGHT_PROP_CUR_ROCK_ENERGY;
|
||||
default -> FIGHT_PROP_NONE;
|
||||
};
|
||||
}
|
||||
|
||||
public static FightProperty getMaxEnergyProp(Element element){
|
||||
return switch (element){
|
||||
case FIRE -> FIGHT_PROP_MAX_FIRE_ENERGY;
|
||||
case WATER -> FIGHT_PROP_MAX_WATER_ENERGY;
|
||||
case GRASS -> FIGHT_PROP_MAX_GRASS_ENERGY;
|
||||
case ELECTRIC -> FIGHT_PROP_MAX_ELEC_ENERGY;
|
||||
case ICE -> FIGHT_PROP_MAX_ICE_ENERGY;
|
||||
case FROZEN -> FIGHT_PROP_MAX_ICE_ENERGY;
|
||||
case WIND -> FIGHT_PROP_MAX_WIND_ENERGY;
|
||||
case ROCK -> FIGHT_PROP_MAX_ROCK_ENERGY;
|
||||
default -> FIGHT_PROP_NONE;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -31,6 +31,8 @@ import org.slf4j.Logger;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.*;
|
||||
|
||||
import org.anime_game_servers.core.gi.enums.QuestState;
|
||||
|
||||
@Entity(value = "quests", useDiscriminator = false)
|
||||
public class GameMainQuest {
|
||||
public static final Logger logger = Loggers.getQuestSystem();
|
||||
@ -264,7 +266,7 @@ public class GameMainQuest {
|
||||
|
||||
if (highestActiveQuest == null) {
|
||||
var firstUnstarted = getChildQuests().values().stream()
|
||||
.filter(q -> q.getQuestData() != null && q.getState().getValue() != QuestState.FINISHED.getValue())
|
||||
.filter(q -> q.getQuestData() != null && q.getState().getValue() != QuestState.QUEST_STATE_FINISHED.getValue())
|
||||
.min(Comparator.comparingInt(a -> a.getQuestData().getOrder()));
|
||||
if(firstUnstarted.isEmpty()){
|
||||
// all quests are probably finished, do don't rewind and maybe also set the mainquest to finished?
|
||||
|
@ -12,10 +12,8 @@ import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.game.props.ActionReason;
|
||||
import emu.grasscutter.game.quest.enums.QuestCond;
|
||||
import emu.grasscutter.game.quest.enums.QuestContent;
|
||||
import emu.grasscutter.game.quest.enums.QuestState;
|
||||
import emu.grasscutter.net.proto.ChapterStateOuterClass;
|
||||
import emu.grasscutter.net.proto.QuestOuterClass.Quest;
|
||||
import emu.grasscutter.scripts.data.SceneGroup;
|
||||
|
||||
import emu.grasscutter.server.packet.send.PacketChapterStateNotify;
|
||||
import emu.grasscutter.server.packet.send.PacketDelQuestNotify;
|
||||
@ -24,6 +22,7 @@ import emu.grasscutter.utils.Utils;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.val;
|
||||
import org.anime_game_servers.core.gi.enums.QuestState;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.script.Bindings;
|
||||
@ -82,7 +81,8 @@ public class GameQuest {
|
||||
}
|
||||
triggerData.put(newTrigger.getTriggerName(), newTrigger);
|
||||
triggers.put(newTrigger.getTriggerName(), false);
|
||||
SceneGroup group = SceneGroup.of(newTrigger.getGroupId()).load(newTrigger.getSceneId());
|
||||
val scene = getOwner().getWorld().getSceneById(newTrigger.getSceneId());
|
||||
val group = scene.getScriptManager().getGroupById(newTrigger.getGroupId());
|
||||
getOwner().getWorld().getSceneById(newTrigger.getSceneId()).loadTriggerFromGroup(group, newTrigger.getTriggerName());
|
||||
}
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import lombok.Getter;
|
||||
import lombok.val;
|
||||
import org.anime_game_servers.core.gi.enums.QuestState;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
|
@ -9,7 +9,7 @@ import emu.grasscutter.game.quest.QuestValueCond;
|
||||
import lombok.val;
|
||||
|
||||
import static emu.grasscutter.game.quest.enums.QuestCond.QUEST_COND_STATE_EQUAL;
|
||||
import static emu.grasscutter.game.quest.enums.QuestState.QUEST_STATE_NONE;
|
||||
import static org.anime_game_servers.core.gi.enums.QuestState.QUEST_STATE_NONE;
|
||||
|
||||
@QuestValueCond(QUEST_COND_STATE_EQUAL)
|
||||
public class ConditionStateEqual extends BaseCondition {
|
||||
|
@ -9,7 +9,7 @@ import emu.grasscutter.game.quest.QuestValueCond;
|
||||
import lombok.val;
|
||||
|
||||
import static emu.grasscutter.game.quest.enums.QuestCond.QUEST_COND_STATE_NOT_EQUAL;
|
||||
import static emu.grasscutter.game.quest.enums.QuestState.QUEST_STATE_NONE;
|
||||
import static org.anime_game_servers.core.gi.enums.QuestState.QUEST_STATE_NONE;
|
||||
|
||||
@QuestValueCond(QUEST_COND_STATE_NOT_EQUAL)
|
||||
public class ConditionStateNotEqual extends BaseCondition {
|
||||
|
@ -7,7 +7,7 @@ import emu.grasscutter.game.quest.QuestValueContent;
|
||||
import lombok.val;
|
||||
|
||||
import static emu.grasscutter.game.quest.enums.QuestContent.QUEST_CONTENT_QUEST_STATE_EQUAL;
|
||||
import static emu.grasscutter.game.quest.enums.QuestState.QUEST_STATE_NONE;
|
||||
import static org.anime_game_servers.core.gi.enums.QuestState.QUEST_STATE_NONE;
|
||||
|
||||
@QuestValueContent(QUEST_CONTENT_QUEST_STATE_EQUAL)
|
||||
public class ContentQuestStateEqual extends BaseContent {
|
||||
|
@ -7,7 +7,7 @@ import emu.grasscutter.game.quest.QuestValueContent;
|
||||
import lombok.val;
|
||||
|
||||
import static emu.grasscutter.game.quest.enums.QuestContent.QUEST_CONTENT_QUEST_STATE_NOT_EQUAL;
|
||||
import static emu.grasscutter.game.quest.enums.QuestState.QUEST_STATE_NONE;
|
||||
import static org.anime_game_servers.core.gi.enums.QuestState.QUEST_STATE_NONE;
|
||||
|
||||
@QuestValueContent(QUEST_CONTENT_QUEST_STATE_NOT_EQUAL)
|
||||
public class ContentQuestStateNotEqual extends BaseContent {
|
||||
|
@ -4,13 +4,13 @@ import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.game.quest.GameQuest;
|
||||
import emu.grasscutter.game.quest.QuestSystem;
|
||||
import emu.grasscutter.game.quest.QuestValueExec;
|
||||
import emu.grasscutter.game.quest.enums.QuestState;
|
||||
import emu.grasscutter.game.quest.enums.QuestExec;
|
||||
import emu.grasscutter.game.quest.handlers.QuestExecHandler;
|
||||
import emu.grasscutter.data.common.quest.SubQuestData.QuestExecParam;
|
||||
import emu.grasscutter.scripts.constants.EventType;
|
||||
import emu.grasscutter.scripts.data.ScriptArgs;
|
||||
import lombok.val;
|
||||
import org.anime_game_servers.core.gi.enums.QuestState;
|
||||
import org.anime_game_servers.gi_lua.models.ScriptArgs;
|
||||
import org.anime_game_servers.gi_lua.models.constants.EventType;
|
||||
|
||||
@QuestValueExec(QuestExec.QUEST_EXEC_NOTIFY_GROUP_LUA)
|
||||
public class ExecNotifyGroupLua extends QuestExecHandler {
|
||||
|
@ -23,22 +23,26 @@ import emu.grasscutter.net.proto.AttackResultOuterClass.AttackResult;
|
||||
import emu.grasscutter.net.proto.VisionTypeOuterClass;
|
||||
import emu.grasscutter.scripts.SceneIndexManager;
|
||||
import emu.grasscutter.scripts.SceneScriptManager;
|
||||
import emu.grasscutter.scripts.constants.EventType;
|
||||
import emu.grasscutter.scripts.data.SceneBlock;
|
||||
import emu.grasscutter.scripts.data.SceneGroup;
|
||||
import emu.grasscutter.scripts.data.SceneInitConfig;
|
||||
import emu.grasscutter.scripts.data.ScriptArgs;
|
||||
import emu.grasscutter.server.event.player.PlayerTeleportEvent;
|
||||
import emu.grasscutter.server.packet.send.*;
|
||||
import emu.grasscutter.utils.KahnsSort;
|
||||
import emu.grasscutter.utils.Position;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import kotlin.Pair;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.val;
|
||||
import messages.gadget.SelectWorktopOptionReq;
|
||||
import messages.scene.EnterType;
|
||||
import messages.scene.VisionType;
|
||||
import org.anime_game_servers.gi_lua.models.SceneGroupUserData;
|
||||
import org.anime_game_servers.gi_lua.models.ScriptArgs;
|
||||
import org.anime_game_servers.gi_lua.models.constants.EventType;
|
||||
import org.anime_game_servers.gi_lua.models.scene.block.SceneBlock;
|
||||
import org.anime_game_servers.gi_lua.models.scene.block.SceneGroupInfo;
|
||||
import org.anime_game_servers.gi_lua.models.scene.group.SceneGroup;
|
||||
import org.anime_game_servers.gi_lua.models.scene.group.SceneInitConfig;
|
||||
import org.anime_game_servers.gi_lua.utils.GroupUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
@ -425,18 +429,20 @@ public class Scene {
|
||||
private void checkPlayerRespawn() {
|
||||
if (this.scriptManager.getConfig() == null) return;
|
||||
|
||||
val diePos = this.scriptManager.getConfig().getDie_y();
|
||||
val diePos = this.scriptManager.getConfig().getDieY();
|
||||
// Check if we need a respawn
|
||||
this.players.stream().filter(p -> diePos >= p.getPosition().getY()).forEach(this::respawnPlayer);
|
||||
this.entities.values().stream().filter(e -> diePos >= e.getPosition().getY()).forEach(this::killEntity);
|
||||
}
|
||||
|
||||
private Position getDefaultLocation(Player player) {
|
||||
return Optional.ofNullable(this.scriptManager.getConfig().getBorn_pos()).orElse(player.getPosition());
|
||||
val bornPost = this.scriptManager.getConfig().getBeginPos();
|
||||
return bornPost != null ? new Position(bornPost) : player.getPosition();
|
||||
}
|
||||
|
||||
private Position getDefaultRot(Player player) {
|
||||
return Optional.ofNullable(this.scriptManager.getConfig().getBorn_rot()).orElse(player.getRotation());
|
||||
val bornPost = this.scriptManager.getConfig().getBornRot();
|
||||
return bornPost != null ? new Position(bornPost) : player.getRotation();
|
||||
}
|
||||
|
||||
private Position getRespawnLocation(Player player) {
|
||||
@ -586,12 +592,6 @@ public class Scene {
|
||||
}
|
||||
}
|
||||
|
||||
public List<SceneBlock> getPlayerActiveBlocks(Player player) {
|
||||
// consider the borders' entities of blocks, so we check if contains by index
|
||||
return SceneIndexManager.queryNeighbors(getScriptManager().getBlocksIndex(),
|
||||
player.getPosition().toXZDoubleArray(), Grasscutter.getConfig().server.game.loadEntitiesForPlayerRange);
|
||||
}
|
||||
|
||||
private Set<Integer> getPlayerActiveGroups(Player player) {
|
||||
// consider the borders' entities of blocks, so we check if contains by index
|
||||
return IntStream.range(0, 4)
|
||||
@ -624,13 +624,12 @@ public class Scene {
|
||||
val visible = this.players.stream().map(this::getPlayerActiveGroups)
|
||||
.flatMap(Collection::stream).collect(Collectors.toSet());
|
||||
|
||||
this.loadedGroups.stream().filter(group -> !visible.contains(group.getId()) && !group.isDynamic_load())
|
||||
.forEach(group -> unloadGroup(this.scriptManager.getBlocks().get(group.block_id), group.getId()));
|
||||
this.loadedGroups.stream().map(SceneGroup::getGroupInfo).filter(group -> !visible.contains(group.getId()) && !group.isDynamicLoad())
|
||||
.forEach(group -> unloadGroup(this.scriptManager.getBlocks().get(group.getBlockId()), group.getId()));
|
||||
|
||||
val toLoad = visible.stream().filter(g -> this.loadedGroups.stream().noneMatch(gr -> gr.getId() == g))
|
||||
.filter(g -> !this.replacedGroup.contains(g)).map(g -> Optional.ofNullable(this.scriptManager.getBlocks())
|
||||
.stream().map(Map::values).flatMap(Collection::stream).peek(this::loadBlock).map(b -> b.getGroups().get(g))
|
||||
.filter(Objects::nonNull).filter(group -> !group.isDynamic_load()).findFirst().orElse(null))
|
||||
val toLoad = visible.stream().filter(g -> this.loadedGroups.stream().noneMatch(gr -> gr.getGroupInfo().getId() == g))
|
||||
.filter(g -> !this.replacedGroup.contains(g)).map(g -> Optional.ofNullable(this.scriptManager.getMeta().getGroups().get(g))
|
||||
.filter(Objects::nonNull).filter(group -> !group.getGroupInfo().isDynamicLoad()).orElse(null))
|
||||
.filter(Objects::nonNull).toList();
|
||||
|
||||
onLoadGroup(toLoad);
|
||||
@ -639,12 +638,18 @@ public class Scene {
|
||||
|
||||
private Set<SceneGroup> onLoadBlock(SceneBlock block, List<Player> players) {
|
||||
if (!block.isLoaded()) {
|
||||
this.scriptManager.loadBlockFromScript(block);
|
||||
Grasscutter.getLogger().info("Scene {} Block {} loaded.", getId(), block.getId());
|
||||
}
|
||||
return this.scriptManager.getLoadedGroupSetPerBlock().computeIfAbsent(block.getId(), f -> new HashSet<>());
|
||||
}
|
||||
|
||||
private Pair<SceneGroupInfo, SceneGroupUserData> getReplaceableGroupsPair(SceneGroup group){
|
||||
return new Pair<>(group.getGroupInfo(), scriptManager.getCachedGroupInstanceById(group.getGroupInfo().getId()));
|
||||
}
|
||||
private Pair<SceneGroupInfo, SceneGroupUserData> getReplaceableGroupsPair(SceneGroupInfo groupInfo){
|
||||
return new Pair<>(groupInfo, scriptManager.getCachedGroupInstanceById(groupInfo.getId()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Load specific (dynamic loaded) group
|
||||
* don't load the group if it was replaced by other groups, TODO should probably log the failed loading reason
|
||||
@ -652,20 +657,28 @@ public class Scene {
|
||||
public int loadDynamicGroup(int groupId) {
|
||||
return this.scriptManager.getGroupInstanceById(groupId) != null || this.replacedGroup.contains(groupId) ? -1 :
|
||||
Optional.ofNullable(this.scriptManager.getGroupById(groupId))
|
||||
.map(SceneGroup::getInit_config).map(SceneInitConfig::getSuite).orElse(-1);
|
||||
.map(SceneGroup::getInitConfig).map(SceneInitConfig::getSuite).orElse(-1);
|
||||
}
|
||||
|
||||
public boolean unregisterDynamicGroup(int groupId){
|
||||
val group = this.scriptManager.getGroupById(groupId);
|
||||
if(group == null) return false;
|
||||
val groupInfo = getReplaceableGroupsPair(group);
|
||||
|
||||
val block = this.scriptManager.getBlocks().get(group.block_id);
|
||||
val block = this.scriptManager.getBlocks().get(group.getGroupInfo().getBlockId());
|
||||
unloadGroup(block, groupId);
|
||||
|
||||
val toRestore = Optional.ofNullable(block.getGroups().get(groupId)).map(g -> g.getReplaceableGroups(block.getGroups().values()))
|
||||
.stream().flatMap(List::stream).filter(replacement -> this.replacedGroup.remove(replacement.getId())).toList();
|
||||
val groupInfoList = block.getGroupInfo().values().stream()
|
||||
.map(this::getReplaceableGroupsPair)
|
||||
.toList();
|
||||
|
||||
val toRestore = Optional.ofNullable(scriptManager.getMeta().getGroups().get(groupId))
|
||||
.map(g -> GroupUtils.getReplaceableGroups(groupInfo, groupInfoList, GameData.getGroupReplacements()))
|
||||
.stream().flatMap(List::stream)
|
||||
.filter(replacement -> this.replacedGroup.remove(replacement.getId()))
|
||||
.toList();
|
||||
if (!toRestore.isEmpty()) {
|
||||
onLoadGroup(toRestore);
|
||||
onLoadGroupInfo(toRestore);
|
||||
Grasscutter.getLogger().info("Unregistered group: {}", groupId);
|
||||
Grasscutter.getLogger().info("Replaced groups: {}", this.replacedGroup);
|
||||
}
|
||||
@ -678,66 +691,87 @@ public class Scene {
|
||||
public void onRegisterGroups() {
|
||||
// Create the graph
|
||||
val groupList = new HashSet<Integer>();
|
||||
val nodes = GameData.getGroupReplacements().values().stream()
|
||||
.filter(replacement -> this.loadedGroups.stream().filter(group -> group.isDynamic_load())
|
||||
.anyMatch(group -> group.getId() == replacement.id)) // dynamic groups
|
||||
// .filter(replacement -> getReplacedGroup().stream().noneMatch(replacement.replace_groups::contains))
|
||||
.peek(replacement -> Grasscutter.getLogger().info("Graph ordering replacement {}", replacement))
|
||||
.peek(replacement -> groupList.add(replacement.id))
|
||||
.peek(replacement -> groupList.addAll(replacement.replace_groups))
|
||||
.map(replacement -> replacement.replace_groups
|
||||
.stream().map(id -> new KahnsSort.Node(replacement.id, id)).toList())
|
||||
val groupIds = this.loadedGroups.stream().map(SceneGroup::getGroupInfo).map(SceneGroupInfo::getId).toList();
|
||||
val replacements = GameData.getGroupReplacements().values().stream()
|
||||
.filter(replacement -> this.loadedGroups.stream()
|
||||
.filter(g-> g.getGroupInfo().isDynamicLoad())
|
||||
.anyMatch(group -> group.getGroupInfo().getId() == replacement.getId())).toList(); // dynamic groups
|
||||
//.filter(replacement -> replacedGroup.stream().noneMatch(replacement.getReplace_groups()::contains))
|
||||
replacements.forEach(replacement -> {
|
||||
Grasscutter.getLogger().info("Graph ordering: replacement {}", replacement);
|
||||
groupList.add(replacement.getId());
|
||||
groupList.addAll(replacement.getReplaceGroups());
|
||||
});
|
||||
|
||||
val nodes = replacements.stream()
|
||||
.map(replacement -> replacement.getReplaceGroups().stream()
|
||||
.map(id -> new KahnsSort.Node(replacement.getId(), id))
|
||||
.toList())
|
||||
.flatMap(List::stream)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
val dynamicGroupsOrdered = KahnsSort.doSort(new KahnsSort.Graph(
|
||||
nodes.stream().toList(), groupList.stream().toList()));
|
||||
|
||||
if(dynamicGroupsOrdered == null) {
|
||||
Grasscutter.getLogger().error("Graph ordering: failed to order dynamic groups");
|
||||
return;
|
||||
}
|
||||
// Now we can start unloading and loading groups :D
|
||||
Optional.ofNullable(KahnsSort.doSort(new KahnsSort.Graph(
|
||||
nodes.stream().toList(), groupList.stream().toList()))).stream().flatMap(List::stream)
|
||||
.map(groupId -> this.loadedGroups.stream().filter(g -> g.getId() == groupId).findFirst()) // isGroupJoinReplacement
|
||||
.filter(Optional::isPresent).map(Optional::get)
|
||||
.map(targetGroup -> targetGroup.getReplaceableGroups(this.loadedGroups))
|
||||
dynamicGroupsOrdered.stream()
|
||||
.map(groupId -> this.loadedGroups.stream().filter(g -> g.getGroupInfo().getId() == groupId).findFirst()) // isGroupJoinReplacement
|
||||
.filter(Optional::isPresent)
|
||||
.map(Optional::get)
|
||||
.map(targetGroup -> GroupUtils.getReplaceableGroups(getReplaceableGroupsPair(targetGroup), this.loadedGroups.stream().map(this::getReplaceableGroupsPair).toList(), GameData.getGroupReplacements()))
|
||||
.flatMap(List::stream)
|
||||
.filter(replacement -> !this.replacedGroup.contains(replacement.getId()))
|
||||
.peek(replacement -> this.replacedGroup.add(replacement.getId()))
|
||||
.peek(replacement -> Grasscutter.getLogger().info("Graph ordering: unloaded {}", replacement.getId()))
|
||||
.peek(replacement -> Grasscutter.getLogger().info("Replaced groups: {}", this.replacedGroup))
|
||||
.forEach(replacement -> unloadGroup(this.scriptManager.getBlocks().get(replacement.block_id), replacement.getId()));
|
||||
.forEach(replacement -> {
|
||||
this.replacedGroup.add(replacement.getId());
|
||||
Grasscutter.getLogger().info("Graph ordering: unloaded {}", replacement.getId());
|
||||
Grasscutter.getLogger().info("Replaced groups: {}", this.replacedGroup);
|
||||
unloadGroup(this.scriptManager.getBlocks().get(replacement.getBlockId()), replacement.getId());
|
||||
});
|
||||
}
|
||||
|
||||
public void loadTriggerFromGroup(SceneGroup group, String triggerName) {
|
||||
//Load triggers and regions
|
||||
this.scriptManager.registerTrigger(group.getTriggers().values().stream().filter(p -> p.getName().contains(triggerName)).toList());
|
||||
group.getRegions().values().stream().filter(q -> q.getConfig_id() == Integer.parseInt(triggerName.substring(13)))
|
||||
group.getRegions().values().stream().filter(q -> q.getConfigId() == Integer.parseInt(triggerName.substring(13)))
|
||||
.map(region -> new EntityRegion(this, region)).forEach(this.scriptManager::registerRegion);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void onLoadGroupInfo(List<org.anime_game_servers.gi_lua.models.scene.block.SceneGroupInfo> groups) {
|
||||
onLoadGroup(groups.stream().map(info -> scriptManager.getMeta().getGroup(info.getId())).toList());
|
||||
}
|
||||
/**
|
||||
* Load specific group(s), used when this
|
||||
* 1) group is came into player's sight (or visible)
|
||||
* 2) group is being registered
|
||||
* */
|
||||
public void onLoadGroup(List<SceneGroup> groups) {
|
||||
public void onLoadGroup(List<org.anime_game_servers.gi_lua.models.scene.group.SceneGroup> groups) {
|
||||
if (groups == null || groups.isEmpty()) return;
|
||||
|
||||
groups.stream().filter(Objects::nonNull).filter(group -> !this.loadedGroups.contains(group))
|
||||
// We load the script files for the groups here
|
||||
.peek(this.scriptManager::loadGroupFromScript)
|
||||
.forEach(group -> onLoadBlock(this.scriptManager.getBlocks().get(group.block_id), getPlayers()).add(group));
|
||||
.forEach(group -> onLoadBlock(this.scriptManager.getBlocks().get(group.getGroupInfo().getBlockId()), getPlayers()).add(group));
|
||||
|
||||
// Spawn gadgets AFTER triggers are added
|
||||
// TODO
|
||||
val entities = new ArrayList<GameEntity>();
|
||||
val entitiesBorn = new ArrayList<GameEntity>();
|
||||
groups.stream().filter(group -> !this.loadedGroups.contains(group)).filter(group -> group.getInit_config() != null)
|
||||
.map(group -> Optional.ofNullable(this.scriptManager.getCachedGroupInstanceById(group.getId()))
|
||||
groups.stream().filter(group -> !this.loadedGroups.contains(group)).filter(group -> group.getInitConfig() != null)
|
||||
.map(group -> Optional.ofNullable(this.scriptManager.getCachedGroupInstanceById(group.getGroupInfo().getId()))
|
||||
.stream().peek(cachedInstance -> cachedInstance.setLuaGroup(group))
|
||||
.findFirst().orElse(this.scriptManager.getGroupInstanceById(group.getId())))
|
||||
.findFirst().orElse(this.scriptManager.getGroupInstanceById(group.getGroupInfo().getId())))
|
||||
.peek(gi -> this.loadedGroups.add(gi.getLuaGroup())) // Load suites
|
||||
.forEach(gi -> this.scriptManager.refreshGroup(gi, 0, false, entitiesBorn)); //This is what the official server does
|
||||
|
||||
this.scriptManager.meetEntities(entities);
|
||||
this.scriptManager.addEntities(entitiesBorn);
|
||||
groups.forEach(g -> this.scriptManager.callEvent(new ScriptArgs(g.getId(), EventType.EVENT_GROUP_LOAD, g.getId())));
|
||||
groups.forEach(g -> this.scriptManager.callEvent(new ScriptArgs(g.getGroupInfo().getId(), EventType.EVENT_GROUP_LOAD, g.getGroupInfo().getId())));
|
||||
Grasscutter.getLogger().info("Scene {} loaded {} group(s)", getId(), groups.size());
|
||||
}
|
||||
|
||||
@ -752,7 +786,7 @@ public class Scene {
|
||||
e.getBlockId() == block.getId() && e.getGroupId() == groupId).toList(), VisionTypeOuterClass.VisionType.VISION_TYPE_REMOVE);
|
||||
|
||||
|
||||
SceneGroup group = block.getGroups().get(groupId);
|
||||
SceneGroup group = scriptManager.getMeta().getGroups().get(groupId);
|
||||
val triggers = group.getTriggers();
|
||||
if (triggers != null) {
|
||||
triggers.values().forEach(getScriptManager()::deregisterTrigger);
|
||||
|
@ -5,6 +5,9 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.anime_game_servers.gi_lua.models.SceneGroupUserData;
|
||||
import org.anime_game_servers.gi_lua.models.scene.group.SceneGadget;
|
||||
import org.anime_game_servers.gi_lua.models.scene.group.SceneGroup;
|
||||
import org.bson.types.ObjectId;
|
||||
|
||||
import dev.morphia.annotations.Entity;
|
||||
@ -12,13 +15,12 @@ import dev.morphia.annotations.Id;
|
||||
import dev.morphia.annotations.Indexed;
|
||||
import emu.grasscutter.database.DatabaseHelper;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.scripts.data.SceneGadget;
|
||||
import emu.grasscutter.scripts.data.SceneGroup;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@Entity(value = "group_instances", useDiscriminator = false)
|
||||
public class SceneGroupInstance {
|
||||
public class SceneGroupInstance implements SceneGroupUserData {
|
||||
@Id private ObjectId id;
|
||||
|
||||
@Indexed private int ownerUid; //This group is owned by the host player
|
||||
@ -34,10 +36,11 @@ public class SceneGroupInstance {
|
||||
@Getter private Map<String, Integer> cachedVariables;
|
||||
|
||||
@Getter @Setter private int lastTimeRefreshed;
|
||||
@Nullable @Getter @Setter private Boolean isReplaceable;
|
||||
|
||||
public SceneGroupInstance(SceneGroup group, Player owner) {
|
||||
this.luaGroup = group;
|
||||
this.groupId = group.getId();
|
||||
this.groupId = group.getGroupInfo().getId();
|
||||
this.targetSuiteId = 0;
|
||||
this.activeSuiteId = 0;
|
||||
this.lastTimeRefreshed = 0;
|
||||
@ -58,7 +61,8 @@ public class SceneGroupInstance {
|
||||
|
||||
public void setLuaGroup(SceneGroup group) {
|
||||
this.luaGroup = group;
|
||||
this.groupId = group.getId();
|
||||
this.groupId = group.getGroupInfo().getId();
|
||||
initWithSceneGroup(group.getGroupInfo());
|
||||
}
|
||||
|
||||
public boolean isCached() {
|
||||
@ -72,15 +76,26 @@ public class SceneGroupInstance {
|
||||
|
||||
public void cacheGadgetState(SceneGadget g, int state) {
|
||||
if(g.isPersistent()) //Only cache when is persistent
|
||||
cachedGadgetStates.put(g.getConfig_id(), state);
|
||||
cachedGadgetStates.put(g.getConfigId(), state);
|
||||
}
|
||||
|
||||
public int getCachedGadgetState(SceneGadget g) {
|
||||
Integer state = cachedGadgetStates.getOrDefault(g.getConfig_id(), null);
|
||||
Integer state = cachedGadgetStates.getOrDefault(g.getConfigId(), null);
|
||||
return (state == null) ? g.getState() : state;
|
||||
}
|
||||
|
||||
public void save() {
|
||||
DatabaseHelper.saveGroupInstance(this);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Boolean isReplaceable() {
|
||||
return isReplaceable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setReplaceable(@Nullable Boolean isReplaceable) {
|
||||
this.isReplaceable = isReplaceable;
|
||||
}
|
||||
}
|
||||
|
@ -310,8 +310,8 @@ public class World implements Iterable<Player> {
|
||||
// }
|
||||
val config = newScene.getScriptManager().getConfig();
|
||||
if (teleportProperties.getTeleportTo() == null && config != null) {
|
||||
Optional.ofNullable(config.getBorn_pos()).map(Position::new).ifPresent(teleportProperties::setTeleportTo);
|
||||
Optional.ofNullable(config.getBorn_rot()).map(Position::new).ifPresent(teleportProperties::setTeleportRot);
|
||||
Optional.ofNullable(config.getBeginPos()).map(Position::new).ifPresent(teleportProperties::setTeleportTo);
|
||||
Optional.ofNullable(config.getBornRot()).map(Position::new).ifPresent(teleportProperties::setTeleportRot);
|
||||
}
|
||||
|
||||
// Set player position and rotation
|
||||
|
@ -11,12 +11,13 @@ 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.scripts.ScriptSystem;
|
||||
import emu.grasscutter.server.game.BaseGameSystem;
|
||||
import emu.grasscutter.server.game.GameServer;
|
||||
import emu.grasscutter.utils.Position;
|
||||
import lombok.val;
|
||||
import org.luaj.vm2.LuaError;
|
||||
import org.anime_game_servers.gi_lua.models.scene.group.SceneGroup;
|
||||
import org.anime_game_servers.gi_lua.models.scene.group.SceneMonster;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@ -68,9 +69,15 @@ public class WorldDataSystem extends BaseGameSystem {
|
||||
|
||||
private SceneGroup getInvestigationGroup(int sceneId, int groupId) {
|
||||
val key = sceneId + "_" + groupId;
|
||||
val sceneMeta = getServer().getScriptSystem().getSceneMeta(sceneId);
|
||||
if (!sceneInvestigationGroupMap.containsKey(key)) {
|
||||
try{
|
||||
val group = SceneGroup.of(groupId).load(sceneId);
|
||||
val group = sceneMeta.getGroup(groupId);
|
||||
if(group == null){
|
||||
Grasscutter.getLogger().error("Null investigationGroup {} in scene{}:", groupId, sceneId);
|
||||
return null;
|
||||
}
|
||||
group.load(ScriptSystem.getScriptLoader());
|
||||
sceneInvestigationGroupMap.putIfAbsent(key, group);
|
||||
return group;
|
||||
} catch (Exception luaError){
|
||||
@ -98,6 +105,7 @@ public class WorldDataSystem extends BaseGameSystem {
|
||||
var groupId = imd.getGroupIdList().get(0);
|
||||
var monsterId = imd.getMonsterIdList().get(0);
|
||||
var sceneId = imd.getCityData().getSceneId();
|
||||
// scene id of the city doesn't match the scene id of the investigation group in some cases ( e.g. investigation data 37 has city 1 (scene 3) but group 155005095 is from scene 5)
|
||||
var group = getInvestigationGroup(sceneId, groupId);
|
||||
|
||||
if (group == null || group.getMonsters() == null) {
|
||||
@ -105,7 +113,7 @@ public class WorldDataSystem extends BaseGameSystem {
|
||||
}
|
||||
|
||||
val monsterOpt = group.getMonsters().values().stream()
|
||||
.filter(x -> x.getMonster_id() == monsterId)
|
||||
.filter(x -> x.getMonsterId() == monsterId)
|
||||
.findFirst();
|
||||
if (monsterOpt.isEmpty()) {
|
||||
return null;
|
||||
@ -128,13 +136,13 @@ public class WorldDataSystem extends BaseGameSystem {
|
||||
.setIsAlive(true)
|
||||
.setNextRefreshTime(Integer.MAX_VALUE)
|
||||
.setRefreshInterval(Integer.MAX_VALUE)
|
||||
.setPos(monsterPos.toProtoOld());
|
||||
.setPos(new Position(monsterPos).toProtoOld());
|
||||
|
||||
if ("Boss".equals(imd.getMonsterCategory())) {
|
||||
var bossChest = group.searchBossChestInGroup();
|
||||
if (bossChest.isPresent()) {
|
||||
builder.setResin(bossChest.get().getResin());
|
||||
builder.setBossChestNum(bossChest.get().getTake_num());
|
||||
builder.setBossChestNum(bossChest.get().getTakeNum());
|
||||
}
|
||||
}
|
||||
return builder.build();
|
||||
|
@ -2,8 +2,8 @@ package emu.grasscutter.scripts;
|
||||
|
||||
import emu.grasscutter.Loggers;
|
||||
import emu.grasscutter.scripts.data.controller.EntityController;
|
||||
import emu.grasscutter.scripts.lua_engine.ScriptType;
|
||||
import lombok.val;
|
||||
import org.anime_game_servers.gi_lua.models.loader.GadgetScriptLoadParams;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.io.IOException;
|
||||
@ -22,6 +22,7 @@ public class EntityControllerScriptManager {
|
||||
}
|
||||
|
||||
private static void cacheGadgetControllers(){
|
||||
val scriptLoader = ScriptSystem.getScriptLoader();
|
||||
try (val stream = Files.newDirectoryStream(getScriptPath("Gadget/"), "*.lua")) {
|
||||
stream.forEach(path -> {
|
||||
val fileName = path.getFileName().toString();
|
||||
@ -30,16 +31,10 @@ public class EntityControllerScriptManager {
|
||||
return;
|
||||
|
||||
val controllerName = fileName.substring(0, fileName.length()-4);
|
||||
val cs = ScriptLoader.getScript("Gadget/"+fileName, ScriptType.EXECUTABLE);
|
||||
if (cs == null)
|
||||
return;
|
||||
|
||||
try{
|
||||
cs.evaluate();
|
||||
val scriptParams = new GadgetScriptLoadParams(fileName);
|
||||
scriptLoader.loadData(scriptParams, cs -> {
|
||||
gadgetController.put(controllerName, new EntityController(cs));
|
||||
} catch (Throwable e){
|
||||
logger.error("Error while loading gadget controller: {}", fileName, e);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
logger.info("Loaded {} gadget controllers", gadgetController.size());
|
||||
|
@ -12,29 +12,35 @@ import emu.grasscutter.data.server.Grid;
|
||||
import emu.grasscutter.database.DatabaseHelper;
|
||||
import emu.grasscutter.game.entity.*;
|
||||
import emu.grasscutter.game.entity.gadget.platform.BaseRoute;
|
||||
import emu.grasscutter.game.props.EntityIdType;
|
||||
import emu.grasscutter.game.quest.GameQuest;
|
||||
import emu.grasscutter.game.quest.QuestGroupSuite;
|
||||
import emu.grasscutter.game.quest.enums.QuestContent;
|
||||
import emu.grasscutter.game.world.Scene;
|
||||
import emu.grasscutter.game.world.SceneGroupInstance;
|
||||
import emu.grasscutter.net.proto.VisionTypeOuterClass;
|
||||
import emu.grasscutter.scripts.constants.EventType;
|
||||
import emu.grasscutter.scripts.data.*;
|
||||
import emu.grasscutter.scripts.lua_engine.LuaValue;
|
||||
import emu.grasscutter.scripts.lua_engine.mock_results.BooleanLuaValue;
|
||||
import emu.grasscutter.scripts.lua_engine.GroupEventLuaContext;
|
||||
import emu.grasscutter.scripts.lua_engine.service.ScriptMonsterSpawnService;
|
||||
import emu.grasscutter.scripts.lua_engine.service.ScriptMonsterTideService;
|
||||
import emu.grasscutter.server.packet.send.PacketGroupSuiteNotify;
|
||||
import emu.grasscutter.utils.FileUtils;
|
||||
import emu.grasscutter.utils.GridPosition;
|
||||
import emu.grasscutter.utils.JsonUtils;
|
||||
import emu.grasscutter.utils.Position;
|
||||
import io.netty.util.concurrent.FastThreadLocalThread;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import kotlin.Pair;
|
||||
import lombok.Getter;
|
||||
import lombok.val;
|
||||
import messages.scene.VisionType;
|
||||
import org.anime_game_servers.gi_lua.models.*;
|
||||
import org.anime_game_servers.gi_lua.models.constants.EventType;
|
||||
import org.anime_game_servers.gi_lua.models.scene.SceneConfig;
|
||||
import org.anime_game_servers.gi_lua.models.scene.SceneMeta;
|
||||
import org.anime_game_servers.gi_lua.models.scene.block.SceneBlock;
|
||||
import org.anime_game_servers.gi_lua.models.scene.block.SceneGroupInfo;
|
||||
import org.anime_game_servers.gi_lua.models.scene.group.*;
|
||||
import org.anime_game_servers.lua.engine.LuaValue;
|
||||
import org.anime_game_servers.lua.models.BooleanLuaValue;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
@ -49,14 +55,14 @@ import java.util.concurrent.*;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static emu.grasscutter.scripts.constants.EventType.*;
|
||||
import static emu.grasscutter.scripts.data.SceneTrigger.INF_TRIGGERS;
|
||||
import static org.anime_game_servers.gi_lua.models.constants.EventType.EVENT_TIMER_EVENT;
|
||||
import static org.anime_game_servers.gi_lua.models.scene.group.SceneTrigger.INF_TRIGGERS;
|
||||
|
||||
public class SceneScriptManager {
|
||||
private static final Logger logger = Loggers.getScriptSystem();
|
||||
private final Scene scene;
|
||||
private final Map<String, Integer> variables;
|
||||
private SceneMeta meta;
|
||||
@Getter private SceneMeta meta;
|
||||
private boolean isInit;
|
||||
/**
|
||||
* current triggers controlled by RefreshGroup
|
||||
@ -154,15 +160,17 @@ public class SceneScriptManager {
|
||||
currentTriggers.put(eventId, ConcurrentHashMap.newKeySet());
|
||||
}
|
||||
|
||||
public void resetTriggersForGroupSuite(SceneGroup group, int suiteIndex) {
|
||||
logger.debug("reset triggers for group {} suite {}", group.getId(), suiteIndex);
|
||||
var suite = group.getSuiteByIndex(suiteIndex);
|
||||
public void resetTriggersForGroupSuite(SceneGroupInstance groupInstance, int suiteIndex) {
|
||||
val groupId = groupInstance.getGroupId();
|
||||
val luaGroup = meta.getGroups().get(groupId);
|
||||
logger.debug("reset triggers for group {} suite {}", groupId, suiteIndex);
|
||||
var suite = luaGroup.getSuiteByIndex(suiteIndex);
|
||||
if (suite == null) {
|
||||
logger.warn("Trying to load null suite Triggers for group {} with suiteindex {}", group.getId(), suiteIndex);
|
||||
logger.warn("Trying to load null suite Triggers for group {} with suiteindex {}", groupId, suiteIndex);
|
||||
return;
|
||||
}
|
||||
|
||||
var groupSceneTriggers = triggersByGroupScene.get(group.getId()+"_"+suiteIndex);
|
||||
var groupSceneTriggers = triggersByGroupScene.get(groupId+"_"+suiteIndex);
|
||||
if(groupSceneTriggers == null){
|
||||
groupSceneTriggers = new HashSet<>();
|
||||
}
|
||||
@ -182,7 +190,7 @@ public class SceneScriptManager {
|
||||
.add(trigger);*/
|
||||
}
|
||||
}
|
||||
triggersByGroupScene.put(group.getId()+"_"+suiteIndex, groupSceneTriggers);
|
||||
triggersByGroupScene.put(groupId+"_"+suiteIndex, groupSceneTriggers);
|
||||
}
|
||||
|
||||
public void refreshGroup(int groupId, int suiteIndex, boolean excludePrevSuite) {
|
||||
@ -207,7 +215,8 @@ public class SceneScriptManager {
|
||||
return refreshGroup(groupInstance, suiteIndex, excludePrevSuite, entitiesAdded, false);
|
||||
}
|
||||
public int refreshGroup(SceneGroupInstance groupInstance, int suiteIndex, boolean excludePrevSuite, List<GameEntity> entitiesAdded, boolean dontLoad) {
|
||||
SceneGroup group = groupInstance.getLuaGroup();
|
||||
val groudId = groupInstance.getGroupId();
|
||||
SceneGroup group = meta.getGroups().get(groudId);
|
||||
if(suiteIndex == 0) {
|
||||
if(excludePrevSuite) {
|
||||
suiteIndex = group.findInitSuiteIndex(groupInstance.getActiveSuiteId());
|
||||
@ -218,7 +227,7 @@ public class SceneScriptManager {
|
||||
|
||||
var suiteData = group.getSuiteByIndex(suiteIndex);
|
||||
if (suiteData == null) {
|
||||
logger.warn("Group {} suite {} not found", group.getId(), suiteIndex);
|
||||
logger.warn("Group {} suite {} not found", groudId, suiteIndex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -228,7 +237,7 @@ public class SceneScriptManager {
|
||||
if(prevSuiteIndex != 0) {
|
||||
prevSuiteData = group.getSuiteByIndex(prevSuiteIndex);
|
||||
if (prevSuiteData != null) {
|
||||
if(prevSuiteData.isBan_refresh() && !suiteData.isBan_refresh()) {
|
||||
if(prevSuiteData.isBanRefresh() && !suiteData.isBanRefresh()) {
|
||||
waitForOne = true;
|
||||
}
|
||||
}
|
||||
@ -236,7 +245,7 @@ public class SceneScriptManager {
|
||||
|
||||
if(waitForOne && (groupInstance.getTargetSuiteId() == 0 || prevSuiteIndex != groupInstance.getTargetSuiteId())) {
|
||||
groupInstance.setTargetSuiteId(suiteIndex);
|
||||
logger.debug("Group {} suite {} wating one more refresh", group.getId(), suiteIndex);
|
||||
logger.debug("Group {} suite {} wating one more refresh", groudId, suiteIndex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -252,7 +261,7 @@ public class SceneScriptManager {
|
||||
|
||||
//Refesh variables here
|
||||
group.getVariables().forEach(variable -> {
|
||||
if(!variable.isNo_refresh())
|
||||
if(!variable.isNoRefresh())
|
||||
groupInstance.getCachedVariables().put(variable.getName(), variable.getValue());
|
||||
});
|
||||
|
||||
@ -305,10 +314,10 @@ public class SceneScriptManager {
|
||||
}
|
||||
val monstersToSpawn = monsters.values().stream()
|
||||
.filter(m -> {
|
||||
var entity = scene.getEntityByConfigId(m.getConfig_id());
|
||||
return (entity == null || entity.getGroupId()!=group.getId());/*&& !groupInstance.getDeadEntities().contains(entity); */ //TODO: Investigate the usage of deadEntities
|
||||
var entity = scene.getEntityByConfigId(m.getConfigId(), groupId);
|
||||
return (entity == null || entity.getGroupId()!=group.getGroupInfo().getId());/*&& !groupInstance.getDeadEntities().contains(entity); */ //TODO: Investigate the usage of deadEntities
|
||||
})
|
||||
.map(mob -> createMonster(group.getId(), group.block_id, mob))
|
||||
.map(mob -> createMonster(group.getGroupInfo().getId(), group.getGroupInfo().getBlockId(), mob))
|
||||
.toList();//TODO check if it interferes with bigworld or anything else
|
||||
this.addEntities(monstersToSpawn);
|
||||
|
||||
@ -320,7 +329,7 @@ public class SceneScriptManager {
|
||||
|
||||
public void registerRegion(EntityRegion region) {
|
||||
regions.put(region.getId(), region);
|
||||
logger.debug("Registered region {} from group {}", region.getMetaRegion().getConfig_id(), region.getGroupId());
|
||||
logger.debug("Registered region {} from group {}", region.getMetaRegion().getConfigId(), region.getGroupId());
|
||||
}
|
||||
public void registerRegionInGroupSuite(SceneGroup group, SceneSuite suite) {
|
||||
suite.getSceneRegions().stream().map(region -> new EntityRegion(this.getScene(), region))
|
||||
@ -328,7 +337,7 @@ public class SceneScriptManager {
|
||||
}
|
||||
public synchronized void deregisterRegion(SceneRegion region) {
|
||||
var instance = regions.values().stream()
|
||||
.filter(r -> r.getConfigId() == region.getConfig_id())
|
||||
.filter(r -> r.getConfigId() == region.getConfigId())
|
||||
.findFirst();
|
||||
instance.ifPresent(entityRegion -> regions.remove(entityRegion.getId()));
|
||||
}
|
||||
@ -339,25 +348,17 @@ public class SceneScriptManager {
|
||||
|
||||
// TODO optimize
|
||||
public SceneGroup getGroupById(int groupId) {
|
||||
for (SceneBlock block : getBlocks().values()) {
|
||||
getScene().loadBlock(block);
|
||||
if(block.getGroups() == null){
|
||||
logger.warn("Block {} in scene {} has no groups", block.getId(), getScene().getId());
|
||||
continue;
|
||||
}
|
||||
val luaGroup = meta.getGroups().get(groupId);
|
||||
|
||||
var group = block.getGroups().get(groupId);
|
||||
if (group == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!this.sceneGroupsInstances.containsKey(groupId)) {
|
||||
getScene().onLoadGroup(List.of(group));
|
||||
getScene().onRegisterGroups();
|
||||
}
|
||||
return group;
|
||||
if(luaGroup == null) {
|
||||
logger.error("Group {} not found in scene {}", groupId, getScene().getId());
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
if (!this.sceneGroupsInstances.containsKey(groupId)) {
|
||||
getScene().onLoadGroup(List.of(luaGroup));
|
||||
getScene().onRegisterGroups();
|
||||
}
|
||||
return luaGroup;
|
||||
}
|
||||
|
||||
public SceneGroupInstance getGroupInstanceById(int groupId) {
|
||||
@ -378,14 +379,14 @@ public class SceneScriptManager {
|
||||
return instance;
|
||||
}
|
||||
|
||||
private static void addEntityGridPosToMap(List<Map<GridPosition, Set<Integer>>> groupPositions, Set<Integer> visionLevels, SceneObject sceneObject, SceneGroup group){
|
||||
private static void addEntityGridPosToMap(List<Map<GridPosition, Set<Integer>>> groupPositions, Set<Integer> visionLevels, SceneObject sceneObject, SceneGroupInfo group){
|
||||
visionLevels.add(addEntityGridPosToMap(groupPositions, sceneObject, group));
|
||||
}
|
||||
private static int addEntityGridPosToMap(List<Map<GridPosition, Set<Integer>>> groupPositions, SceneObject sceneObject, SceneGroup group){
|
||||
private static int addEntityGridPosToMap(List<Map<GridPosition, Set<Integer>>> groupPositions, SceneObject sceneObject, SceneGroupInfo group){
|
||||
val visionLevel = switch (sceneObject.getType()){
|
||||
case GADGET -> Math.max(getGadgetVisionLevel(((SceneGadget)sceneObject).getGadget_id()), sceneObject.getVision_level());
|
||||
case GADGET -> Math.max(getGadgetVisionLevel(((SceneGadget)sceneObject).getGadgetId()), sceneObject.getVisionLevel());
|
||||
case REGION -> 0;
|
||||
default -> sceneObject.getVision_level();
|
||||
default -> sceneObject.getVisionLevel();
|
||||
};
|
||||
addGridPositionToMap(groupPositions.get(visionLevel), group.getId(), visionLevel, sceneObject.getPos());
|
||||
return visionLevel;
|
||||
@ -416,11 +417,13 @@ public class SceneScriptManager {
|
||||
}
|
||||
|
||||
private void init() {
|
||||
var meta = ScriptLoader.getSceneMeta(getScene().getId());
|
||||
val scriptSystem = getScene().getWorld().getHost().getServer().getScriptSystem();
|
||||
var meta = scriptSystem.getSceneMeta(getScene().getId());
|
||||
if (meta == null) {
|
||||
return;
|
||||
}
|
||||
this.meta = meta;
|
||||
meta.loadActivity(ScriptSystem.getScriptLoader(), 2001);
|
||||
|
||||
// TEMP
|
||||
this.isInit = true;
|
||||
@ -448,63 +451,58 @@ public class SceneScriptManager {
|
||||
for (int i = 0; i < 6; i++) groupPositions.add(new HashMap<>());
|
||||
|
||||
var visionOptions = Grasscutter.config.server.game.visionOptions;
|
||||
meta.getBlocks().values().forEach(block -> {
|
||||
block.load(sceneId);
|
||||
if(block.getGroups() == null){
|
||||
logger.error("block.groups null for block {}", block.getId());
|
||||
return;
|
||||
val scriptLoader = ScriptSystem.getScriptLoader();
|
||||
meta.getGroups().values().stream().filter(g -> !g.getGroupInfo().isDynamicLoad()).forEach(group -> {
|
||||
val groupInfo = group.getGroupInfo();
|
||||
val groupId = groupInfo.getId();
|
||||
group.load(scriptLoader);
|
||||
|
||||
//Add all entities here
|
||||
Set<Integer> vision_levels = new HashSet<>();
|
||||
|
||||
val monsters = group.getMonsters();
|
||||
if (monsters != null) {
|
||||
monsters.values().forEach(m -> addEntityGridPosToMap(groupPositions, vision_levels, m, groupInfo));
|
||||
} else {
|
||||
logger.error("group.monsters null for group {}", groupId);
|
||||
}
|
||||
val gadgets = group.getGadgets();
|
||||
if (gadgets != null) {
|
||||
gadgets.values().forEach(g -> addEntityGridPosToMap(groupPositions, vision_levels, g, groupInfo));
|
||||
} else {
|
||||
logger.error("group.gadgets null for group {}", groupId);
|
||||
}
|
||||
logger.debug("Loading block grid " + block.getId());
|
||||
block.getGroups().values().stream().filter(g -> !g.isDynamic_load()).forEach(group -> {
|
||||
group.load(this.scene.getId());
|
||||
|
||||
//Add all entities here
|
||||
Set<Integer> vision_levels = new HashSet<>();
|
||||
val npcs = group.getNpcs();
|
||||
if (npcs != null) {
|
||||
npcs.values().forEach(n -> addEntityGridPosToMap(groupPositions, n, groupInfo));
|
||||
} else {
|
||||
logger.error("group.npcs null for group {}", groupId);
|
||||
}
|
||||
|
||||
val monsters = group.getMonsters();
|
||||
if (monsters != null) {
|
||||
monsters.values().forEach(m -> addEntityGridPosToMap(groupPositions, vision_levels, m, group));
|
||||
} else {
|
||||
logger.error("group.monsters null for group {}", group.getId());
|
||||
}
|
||||
val gadgets = group.getGadgets();
|
||||
if (gadgets != null) {
|
||||
gadgets.values().forEach(g -> addEntityGridPosToMap(groupPositions, vision_levels, g, group));
|
||||
} else {
|
||||
logger.error("group.gadgets null for group {}", group.getId());
|
||||
val regions = group.getRegions();
|
||||
if (regions != null) {
|
||||
regions.values().forEach(r -> addEntityGridPosToMap(groupPositions, r, groupInfo));
|
||||
} else {
|
||||
logger.error("group.regions null for group {}", groupId);
|
||||
}
|
||||
|
||||
// TODO should we add those to the grid?
|
||||
val garbages = group.getGarbages();
|
||||
if (garbages != null && garbages.getGadgets() != null) {
|
||||
garbages.getGadgets().forEach(g -> addEntityGridPosToMap(groupPositions, g, groupInfo));
|
||||
}
|
||||
|
||||
int max_vision_level = -1;
|
||||
if (!vision_levels.isEmpty()) {
|
||||
for (int vision_level : vision_levels) {
|
||||
if (max_vision_level == -1 || visionOptions[max_vision_level].visionRange < visionOptions[vision_level].visionRange)
|
||||
max_vision_level = vision_level;
|
||||
}
|
||||
}
|
||||
if (max_vision_level == -1) max_vision_level = 0;
|
||||
|
||||
val npcs = group.getNpcs();
|
||||
if (npcs != null) {
|
||||
npcs.values().forEach(n -> addEntityGridPosToMap(groupPositions, n, group));
|
||||
} else {
|
||||
logger.error("group.npcs null for group {}", group.getId());
|
||||
}
|
||||
|
||||
val regions = group.getRegions();
|
||||
if (regions != null) {
|
||||
regions.values().forEach(r -> addEntityGridPosToMap(groupPositions, r, group));
|
||||
} else {
|
||||
logger.error("group.regions null for group {}", group.getId());
|
||||
}
|
||||
|
||||
// TODO should we add those to the grid?
|
||||
val garbages = group.getGarbages();
|
||||
if (garbages != null && garbages.getGadgets() != null) {
|
||||
garbages.getGadgets().forEach(g -> addEntityGridPosToMap(groupPositions, g, group));
|
||||
}
|
||||
|
||||
int max_vision_level = -1;
|
||||
if (!vision_levels.isEmpty()) {
|
||||
for (int vision_level : vision_levels) {
|
||||
if (max_vision_level == -1 || visionOptions[max_vision_level].visionRange < visionOptions[vision_level].visionRange)
|
||||
max_vision_level = vision_level;
|
||||
}
|
||||
}
|
||||
if (max_vision_level == -1) max_vision_level = 0;
|
||||
|
||||
addGridPositionToMap(groupPositions.get(max_vision_level), group.getId(), max_vision_level, group.getPos());
|
||||
});
|
||||
addGridPositionToMap(groupPositions.get(max_vision_level), groupInfo.getId(), max_vision_level, groupInfo.getPos());
|
||||
});
|
||||
|
||||
var groupGrids = new ArrayList<Grid>();
|
||||
@ -531,28 +529,26 @@ public class SceneScriptManager {
|
||||
return isInit;
|
||||
}
|
||||
|
||||
public void loadBlockFromScript(SceneBlock block) {
|
||||
block.load(scene.getId());
|
||||
}
|
||||
|
||||
public void loadGroupFromScript(SceneGroup group) {
|
||||
group.load(getScene().getId());
|
||||
val scriptLoader = ScriptSystem.getScriptLoader();
|
||||
val groupId = group.getGroupInfo().getId();
|
||||
group.load(scriptLoader);
|
||||
|
||||
this.sceneGroups.put(group.getId(), group);
|
||||
if(this.getCachedGroupInstanceById(group.getId()) != null) {
|
||||
this.sceneGroupsInstances.put(group.getId(), this.cachedSceneGroupsInstances.get(group.getId()));
|
||||
this.cachedSceneGroupsInstances.get(group.getId()).setCached(false);
|
||||
this.cachedSceneGroupsInstances.get(group.getId()).setLuaGroup(group);
|
||||
this.sceneGroups.put(groupId, group);
|
||||
if(this.getCachedGroupInstanceById(groupId) != null) {
|
||||
this.sceneGroupsInstances.put(groupId, this.cachedSceneGroupsInstances.get(groupId));
|
||||
this.cachedSceneGroupsInstances.get(groupId).setCached(false);
|
||||
this.cachedSceneGroupsInstances.get(groupId).setLuaGroup(group);
|
||||
} else {
|
||||
var instance = new SceneGroupInstance(group, getScene().getWorld().getHost());
|
||||
this.sceneGroupsInstances.put(group.getId(), instance);
|
||||
this.cachedSceneGroupsInstances.put(group.getId(), instance);
|
||||
this.sceneGroupsInstances.put(groupId, instance);
|
||||
this.cachedSceneGroupsInstances.put(groupId, instance);
|
||||
instance.save(); //Save the instance
|
||||
}
|
||||
|
||||
if (group.getVariables() != null) {
|
||||
group.getVariables().forEach(variable -> {
|
||||
val variables = this.getVariables(group.getId());
|
||||
val variables = this.getVariables(groupId);
|
||||
if(variables != null && !variables.containsKey(variable.getName()))
|
||||
variables.put(variable.getName(), variable.getValue());
|
||||
});
|
||||
@ -560,7 +556,7 @@ public class SceneScriptManager {
|
||||
}
|
||||
|
||||
public void unregisterGroup(SceneGroup group) {
|
||||
this.sceneGroups.remove(group.getId());
|
||||
this.sceneGroups.remove(group.getGroupInfo().getId());
|
||||
this.sceneGroupsInstances.values().removeIf(i -> i.getLuaGroup().equals(group));
|
||||
this.cachedSceneGroupsInstances.values().stream().filter(i -> Objects.equals(i.getLuaGroup(),group)).forEach(s -> s.setCached(true));
|
||||
}
|
||||
@ -602,25 +598,27 @@ public class SceneScriptManager {
|
||||
}
|
||||
|
||||
public List<EntityGadget> getGadgetsInGroupSuite(SceneGroupInstance groupInstance, SceneSuite suite) {
|
||||
var group = groupInstance.getLuaGroup();
|
||||
val group = groupInstance.getLuaGroup();
|
||||
val groupId = group.getGroupInfo().getId();
|
||||
return suite.getSceneGadgets().stream()
|
||||
.filter(m -> {
|
||||
var entity = scene.getEntityByConfigId(m.getConfig_id());
|
||||
return (entity == null || entity.getGroupId()!=group.getId()) && (!m.isOneoff() || !m.isPersistent() || !groupInstance.getDeadEntities().contains(m.getConfig_id()));
|
||||
val entity = scene.getEntityByConfigId(m.getConfigId(), groupId);
|
||||
return (entity == null || entity.getGroupId()!=groupId) && (!m.isOneOff() || !m.isPersistent() || !groupInstance.getDeadEntities().contains(m.getConfigId()));
|
||||
})
|
||||
.map(g -> createGadget(group.getId(), group.block_id, g, groupInstance.getCachedGadgetState(g)))
|
||||
.peek(g -> groupInstance.cacheGadgetState(g.getMetaGadget(), g.getState()))
|
||||
.map(g -> createGadget(groupId, group.getGroupInfo().getBlockId(), g, groupInstance.getCachedGadgetState(g)))
|
||||
.filter(Objects::nonNull)
|
||||
.peek(g -> groupInstance.cacheGadgetState(g.getMetaGadget(), g.getState()))
|
||||
.toList();
|
||||
}
|
||||
public List<EntityMonster> getMonstersInGroupSuite(SceneGroupInstance groupInstance, SceneSuite suite) {
|
||||
var group = groupInstance.getLuaGroup();
|
||||
val group = groupInstance.getLuaGroup();
|
||||
val groupId = group.getGroupInfo().getId();
|
||||
return suite.getSceneMonsters().stream()
|
||||
.filter(m -> {
|
||||
var entity = scene.getEntityByConfigId(m.getConfig_id());
|
||||
return (entity == null || entity.getGroupId()!=group.getId());/*&& !groupInstance.getDeadEntities().contains(entity); */ //TODO: Investigate the usage of deadEntities
|
||||
var entity = scene.getEntityByConfigId(m.getConfigId(), groupId);
|
||||
return (entity == null || entity.getGroupId()!=groupId);/*&& !groupInstance.getDeadEntities().contains(entity); */ //TODO: Investigate the usage of deadEntities
|
||||
}) //TODO: Add persistent monster cached data
|
||||
.map(mob -> createMonster(group.getId(), group.block_id, mob))
|
||||
.map(mob -> createMonster(groupId, group.getGroupInfo().getBlockId(), mob))
|
||||
.filter(Objects::nonNull)
|
||||
.toList();
|
||||
}
|
||||
@ -684,26 +682,27 @@ public class SceneScriptManager {
|
||||
}
|
||||
public void spawnMonstersByConfigId(SceneGroup group, int configId, int delayTime) {
|
||||
// TODO delay
|
||||
var entity = scene.getEntityByConfigId(configId);
|
||||
if(entity!=null && entity.getGroupId() == group.getId()){
|
||||
logger.debug("entity already exists failed in group {} with config {}", group.getId(), configId);
|
||||
val groupId = group.getGroupInfo().getId();
|
||||
var entity = scene.getEntityByConfigId(configId, groupId);
|
||||
if(entity!=null && entity.getGroupId() == groupId){
|
||||
logger.debug("entity already exists failed in group {} with config {}", groupId, configId);
|
||||
return;
|
||||
}
|
||||
val groupMonsters = group.getMonsters();
|
||||
if(groupMonsters == null){
|
||||
logger.warn("monsters in group {} are null, unable to get configId {}", group.getId(), configId);
|
||||
logger.warn("monsters in group {} are null, unable to get configId {}", groupId, configId);
|
||||
return;
|
||||
}
|
||||
val monster = groupMonsters.get(configId);
|
||||
if(monster == null){
|
||||
logger.warn("configId {} not found in group {}", configId, group.getId());
|
||||
logger.warn("configId {} not found in group {}", configId, groupId);
|
||||
return;
|
||||
}
|
||||
entity = createMonster(group.getId(), group.block_id, monster);
|
||||
entity = createMonster(groupId, group.getGroupInfo().getBlockId(), monster);
|
||||
if(entity!=null){
|
||||
getScene().addEntity(entity);
|
||||
} else {
|
||||
logger.warn("failed to create entity with group {} and config {}", group.getId(), configId);
|
||||
logger.warn("failed to create entity with group {} and config {}", groupId, configId);
|
||||
}
|
||||
}
|
||||
// Events
|
||||
@ -724,7 +723,7 @@ public class SceneScriptManager {
|
||||
try {
|
||||
int eventType = params.type;
|
||||
Set<SceneTrigger> relevantTriggers = this.getTriggersByEvent(eventType).stream()
|
||||
.filter(t -> params.getGroupId() == 0 || t.getCurrentGroup().getId() == params.getGroupId())
|
||||
.filter(t -> params.getGroupId() == 0 || t.getGroupId() == params.getGroupId())
|
||||
.filter(t -> (t.getSource().isEmpty() || t.getSource().equals(params.getEventSource())))
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
@ -739,8 +738,9 @@ public class SceneScriptManager {
|
||||
private boolean handleEventForTrigger(ScriptArgs params, SceneTrigger trigger ){
|
||||
logger.debug("checking trigger {} for event {}", trigger.getName(), params.type);
|
||||
try {
|
||||
if (evaluateTriggerCondition(trigger, params)) {
|
||||
callTrigger(trigger, params);
|
||||
val group = trigger.getSceneMeta().getGroup(trigger.getGroupId());
|
||||
if (evaluateTriggerCondition(trigger, group, params)) {
|
||||
callTrigger(trigger, group, params);
|
||||
return true;
|
||||
} else {
|
||||
logger.debug("Condition Trigger {} returned false", trigger.getCondition());
|
||||
@ -760,22 +760,22 @@ public class SceneScriptManager {
|
||||
* @param params
|
||||
* @return true if there is no condition, otherwise the result of the condition call as boolean
|
||||
*/
|
||||
private boolean evaluateTriggerCondition(SceneTrigger trigger, ScriptArgs params){
|
||||
private boolean evaluateTriggerCondition(SceneTrigger trigger, SceneGroup group, ScriptArgs params){
|
||||
logger.trace("Call Condition Trigger {}, [{},{},{}]", trigger.getCondition(), params.param1, params.source_eid, params.target_eid);
|
||||
val condition = trigger.getCondition();
|
||||
if(condition == null || condition.isBlank()){
|
||||
return true;
|
||||
}
|
||||
val ret = this.callScriptFunc(trigger.getCondition(), trigger.getCurrentGroup(), params);
|
||||
val ret = this.callScriptFunc(trigger.getCondition(), group, params);
|
||||
return ret.isBoolean() && ret.asBoolean();
|
||||
}
|
||||
|
||||
private void callTrigger(SceneTrigger trigger, ScriptArgs params){
|
||||
private void callTrigger(SceneTrigger trigger, SceneGroup group, ScriptArgs params){
|
||||
val action = trigger.getAction();
|
||||
LuaValue callResult = BooleanLuaValue.TRUE;
|
||||
if(action != null && !action.isBlank()){
|
||||
// the SetGroupVariableValueByGroup in tower need the param to record the first stage time
|
||||
callResult = this.callScriptFunc(trigger.getAction(), trigger.getCurrentGroup(), params);
|
||||
callResult = this.callScriptFunc(trigger.getAction(), group, params);
|
||||
}
|
||||
|
||||
val invocationsCounter = triggerInvocations.get(trigger.getName());
|
||||
@ -797,7 +797,7 @@ public class SceneScriptManager {
|
||||
}
|
||||
|
||||
if(trigger.getEvent() == EVENT_TIMER_EVENT){
|
||||
cancelGroupTimerEvent(trigger.getCurrentGroup().getId(), trigger.getSource());
|
||||
cancelGroupTimerEvent(trigger.getGroupId(), trigger.getSource());
|
||||
}
|
||||
// always deregister on error, otherwise only if the count is reached
|
||||
if(callResult.isBoolean() && !callResult.asBoolean() || callResult.isInteger() && callResult.asInteger()!=0
|
||||
@ -822,11 +822,11 @@ public class SceneScriptManager {
|
||||
return BooleanLuaValue.FALSE;
|
||||
}
|
||||
|
||||
val context = script.getGroupEventLuaContext(group, params, this);
|
||||
val context = new GroupEventLuaContext(script.getEngine(), group, params, this);
|
||||
try{
|
||||
return script.callMethod(funcName, context, params);
|
||||
} catch (RuntimeException | ScriptException | NoSuchMethodException error){
|
||||
logger.error("[LUA] call trigger failed in group {} with {},{}",group.getId(),funcName,params,error);
|
||||
logger.error("[LUA] call trigger failed in group {} with {},{}",group.getGroupInfo().getId(),funcName,params,error);
|
||||
return new BooleanLuaValue(false);
|
||||
}
|
||||
}
|
||||
@ -844,29 +844,29 @@ public class SceneScriptManager {
|
||||
}
|
||||
|
||||
public EntityGadget createGadget(int groupId, int blockId, SceneGadget g, int state) {
|
||||
if (g.isOneoff()) {
|
||||
if (g.isOneOff()) {
|
||||
var hasEntity = getScene().getEntities().values().stream()
|
||||
.filter(e -> e instanceof EntityGadget)
|
||||
.filter(e -> e.getGroupId() == g.getGroup().getId())
|
||||
.filter(e -> e.getConfigId() == g.getConfig_id())
|
||||
.filter(e -> e.getGroupId() == g.getGroupId())
|
||||
.filter(e -> e.getConfigId() == g.getConfigId())
|
||||
.findFirst();
|
||||
if (hasEntity.isPresent()) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
EntityGadget entity = new EntityGadget(getScene(), g.getGadget_id(), g.getPos());
|
||||
EntityGadget entity = new EntityGadget(getScene(), g.getGadgetId(), new emu.grasscutter.utils.Position(g.getPos()));
|
||||
|
||||
if (entity.getGadgetData() == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
entity.setBlockId(blockId);
|
||||
entity.setConfigId(g.getConfig_id());
|
||||
entity.setConfigId(g.getConfigId());
|
||||
entity.setGroupId(groupId);
|
||||
entity.getRotation().set(g.getRot());
|
||||
entity.setState(state);
|
||||
|
||||
entity.setPointType(g.getPoint_type());
|
||||
entity.setPointType(g.getPointType());
|
||||
entity.setRouteConfig(BaseRoute.fromSceneGadget(g));
|
||||
entity.setMetaGadget(g);
|
||||
entity.buildContent();
|
||||
@ -881,7 +881,7 @@ public class SceneScriptManager {
|
||||
return null;
|
||||
}
|
||||
|
||||
MonsterData data = GameData.getMonsterDataMap().get(monster.getMonster_id());
|
||||
MonsterData data = GameData.getMonsterDataMap().get(monster.getMonsterId());
|
||||
|
||||
if (data == null) {
|
||||
return null;
|
||||
@ -891,7 +891,7 @@ public class SceneScriptManager {
|
||||
int level = monster.getLevel();
|
||||
|
||||
if (getScene().getDungeonManager() != null) {
|
||||
level = getScene().getDungeonManager().getLevelForMonster(monster.getConfig_id());
|
||||
level = getScene().getDungeonManager().getLevelForMonster(monster.getConfigId());
|
||||
} else if (getScene().getWorld().getWorldLevel() > 0) {
|
||||
WorldLevelData worldLevelData = GameData.getWorldLevelDataMap().get(getScene().getWorld().getWorldLevel());
|
||||
|
||||
@ -901,12 +901,12 @@ public class SceneScriptManager {
|
||||
}
|
||||
|
||||
// Spawn mob
|
||||
EntityMonster entity = new EntityMonster(getScene(), data, monster.getPos(), level);
|
||||
EntityMonster entity = new EntityMonster(getScene(), data, new emu.grasscutter.utils.Position(monster.getPos()), level);
|
||||
entity.getRotation().set(monster.getRot());
|
||||
entity.setGroupId(groupId);
|
||||
entity.setBlockId(blockId);
|
||||
entity.setConfigId(monster.getConfig_id());
|
||||
entity.setPoseId(monster.getPose_id());
|
||||
entity.setConfigId(monster.getConfigId());
|
||||
entity.setPoseId(monster.getPoseId());
|
||||
entity.setMetaMonster(monster);
|
||||
|
||||
this.getScriptMonsterSpawnService()
|
||||
@ -920,7 +920,7 @@ public class SceneScriptManager {
|
||||
}
|
||||
|
||||
public void meetEntities(List<? extends GameEntity> gameEntity) {
|
||||
getScene().addEntities(gameEntity, VisionTypeOuterClass.VisionType.VISION_TYPE_MEET);
|
||||
getScene().addEntities(gameEntity, VisionType.VISION_MEET);
|
||||
}
|
||||
|
||||
public void addEntities(List<? extends GameEntity> gameEntity) {
|
||||
@ -931,16 +931,13 @@ public class SceneScriptManager {
|
||||
getScene().removeEntities(gameEntity.stream().map(e -> (GameEntity) e).collect(Collectors.toList()), VisionTypeOuterClass.VisionType.VISION_TYPE_REFRESH);
|
||||
}
|
||||
|
||||
public RTree<SceneBlock, Geometry> getBlocksIndex() {
|
||||
return meta.getSceneBlockIndex();
|
||||
}
|
||||
public void removeMonstersInGroup(SceneGroup group, SceneSuite suite) {
|
||||
var configSet = suite.getSceneMonsters().stream()
|
||||
.map(SceneObject::getConfig_id)
|
||||
.map(SceneObject::getConfigId)
|
||||
.collect(Collectors.toSet());
|
||||
var toRemove = getScene().getEntities().values().stream()
|
||||
.filter(e -> e instanceof EntityMonster)
|
||||
.filter(e -> e.getGroupId() == group.getId())
|
||||
.filter(e -> e.getGroupId() == group.getGroupInfo().getId())
|
||||
.filter(e -> configSet.contains(e.getConfigId()))
|
||||
.toList();
|
||||
|
||||
@ -948,11 +945,11 @@ public class SceneScriptManager {
|
||||
}
|
||||
public void removeGadgetsInGroup(SceneGroup group, SceneSuite suite) {
|
||||
var configSet = suite.getSceneGadgets().stream()
|
||||
.map(SceneObject::getConfig_id)
|
||||
.map(SceneObject::getConfigId)
|
||||
.collect(Collectors.toSet());
|
||||
var toRemove = getScene().getEntities().values().stream()
|
||||
.filter(e -> e instanceof EntityGadget)
|
||||
.filter(e -> e.getGroupId() == group.getId())
|
||||
.filter(e -> e.getGroupId() == group.getGroupInfo().getId())
|
||||
.filter(e -> configSet.contains(e.getConfigId()))
|
||||
.toList();
|
||||
|
||||
@ -961,11 +958,11 @@ public class SceneScriptManager {
|
||||
|
||||
public void killMonstersInGroup(SceneGroup group, SceneSuite suite) {
|
||||
var configSet = suite.getSceneMonsters().stream()
|
||||
.map(SceneObject::getConfig_id)
|
||||
.map(SceneObject::getConfigId)
|
||||
.collect(Collectors.toSet());
|
||||
var toRemove = getScene().getEntities().values().stream()
|
||||
.filter(e -> e instanceof EntityMonster)
|
||||
.filter(e -> e.getGroupId() == group.getId())
|
||||
.filter(e -> e.getGroupId() == group.getGroupInfo().getId())
|
||||
.filter(e -> configSet.contains(e.getConfigId()))
|
||||
.toList();
|
||||
|
||||
@ -973,11 +970,11 @@ public class SceneScriptManager {
|
||||
}
|
||||
public void killGadgetsInGroup(SceneGroup group, SceneSuite suite) {
|
||||
var configSet = suite.getSceneGadgets().stream()
|
||||
.map(SceneObject::getConfig_id)
|
||||
.map(SceneObject::getConfigId)
|
||||
.collect(Collectors.toSet());
|
||||
var toRemove = getScene().getEntities().values().stream()
|
||||
.filter(e -> e instanceof EntityGadget)
|
||||
.filter(e -> e.getGroupId() == group.getId())
|
||||
.filter(e -> e.getGroupId() == group.getGroupInfo().getId())
|
||||
.filter(e -> configSet.contains(e.getConfigId()))
|
||||
.toList();
|
||||
|
||||
@ -1035,7 +1032,7 @@ public class SceneScriptManager {
|
||||
if(monsters == null || monsters.isEmpty()) return true;
|
||||
|
||||
return monsters.values().stream().noneMatch(m -> {
|
||||
val entity = scene.getEntityByConfigId(m.getConfig_id());
|
||||
val entity = scene.getEntityByConfigId(m.getConfigId(), groupId);
|
||||
return entity != null && entity.getGroupId() == groupId;
|
||||
});
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
1936
src/main/java/emu/grasscutter/scripts/ScriptLibHandler.java
Normal file
1936
src/main/java/emu/grasscutter/scripts/ScriptLibHandler.java
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,111 +0,0 @@
|
||||
package emu.grasscutter.scripts;
|
||||
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.Loggers;
|
||||
import emu.grasscutter.game.dungeons.challenge.enums.ChallengeEventMarkType;
|
||||
import emu.grasscutter.game.dungeons.challenge.enums.FatherChallengeProperty;
|
||||
import emu.grasscutter.game.props.ElementType;
|
||||
import emu.grasscutter.game.props.EntityType;
|
||||
import emu.grasscutter.game.quest.enums.QuestState;
|
||||
import emu.grasscutter.scripts.constants.*;
|
||||
import emu.grasscutter.scripts.constants.temporary.ExhibitionPlayType;
|
||||
import emu.grasscutter.scripts.constants.temporary.FlowSuiteOperatePolicy;
|
||||
import emu.grasscutter.scripts.constants.temporary.GalleryProgressScoreType;
|
||||
import emu.grasscutter.scripts.constants.temporary.GalleryProgressScoreUIType;
|
||||
import emu.grasscutter.scripts.data.SceneMeta;
|
||||
import emu.grasscutter.scripts.lua_engine.LuaEngine;
|
||||
import emu.grasscutter.scripts.lua_engine.LuaScript;
|
||||
import emu.grasscutter.scripts.lua_engine.ScriptType;
|
||||
import emu.grasscutter.scripts.lua_engine.jnlua.JNLuaEngine;
|
||||
import emu.grasscutter.scripts.lua_engine.luaj.LuaJEngine;
|
||||
import lombok.Getter;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class ScriptLoader {
|
||||
@Getter private static LuaEngine luaEngine;
|
||||
private static final Logger logger = Loggers.getScriptSystem();
|
||||
/**
|
||||
* suggest GC to remove it if the memory is less
|
||||
*/
|
||||
private static Map<String, SoftReference<LuaScript>> scriptsCache = new ConcurrentHashMap<>();
|
||||
/**
|
||||
* sceneId - SceneMeta
|
||||
*/
|
||||
private static Map<Integer, SoftReference<SceneMeta>> sceneMetaCache = new ConcurrentHashMap<>();
|
||||
|
||||
public synchronized static void init() throws Exception {
|
||||
if (luaEngine != null) {
|
||||
throw new Exception("Script loader already initialized");
|
||||
}
|
||||
|
||||
// Create script engine
|
||||
if(Grasscutter.getConfig().server.game.useJNLua){
|
||||
logger.info("Using JNLua");
|
||||
luaEngine = new JNLuaEngine();
|
||||
} else {
|
||||
logger.info("Using LuaJ");
|
||||
luaEngine = new LuaJEngine();
|
||||
}
|
||||
|
||||
luaEngine.addGlobalEnumByIntValue("EntityType", EntityType.values());
|
||||
luaEngine.addGlobalEnumByIntValue("QuestState", QuestState.values());
|
||||
luaEngine.addGlobalEnumByIntValue("ElementType", ElementType.values());
|
||||
|
||||
luaEngine.addGlobalEnumByOrdinal("GroupKillPolicy", GroupKillPolicy.values());
|
||||
luaEngine.addGlobalEnumByOrdinal("SealBattleType", SealBattleType.values());
|
||||
luaEngine.addGlobalEnumByOrdinal("FatherChallengeProperty", FatherChallengeProperty.values());
|
||||
luaEngine.addGlobalEnumByOrdinal("ChallengeEventMarkType", ChallengeEventMarkType.values());
|
||||
luaEngine.addGlobalEnumByOrdinal("VisionLevelType", VisionLevelType.values());
|
||||
luaEngine.addGlobalEnumByOrdinal("ExhibitionPlayType", ExhibitionPlayType.values());
|
||||
luaEngine.addGlobalEnumByOrdinal("FlowSuiteOperatePolicy", FlowSuiteOperatePolicy.values());
|
||||
luaEngine.addGlobalEnumByOrdinal("GalleryProgressScoreUIType", GalleryProgressScoreUIType.values());
|
||||
luaEngine.addGlobalEnumByOrdinal("GalleryProgressScoreType", GalleryProgressScoreType.values());
|
||||
|
||||
luaEngine.addGlobalStaticClass("EventType", EventType.class);
|
||||
luaEngine.addGlobalStaticClass("GadgetState", ScriptGadgetState.class);
|
||||
luaEngine.addGlobalStaticClass("RegionShape", ScriptRegionShape.class);
|
||||
luaEngine.addGlobalStaticClass("ScriptLib", ScriptLib.class);
|
||||
}
|
||||
|
||||
public static <T> Optional<T> tryGet(SoftReference<T> softReference) {
|
||||
try {
|
||||
return Optional.ofNullable(softReference.get());
|
||||
}catch (NullPointerException npe) {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
public static LuaScript getScript(String path, ScriptType scriptType) {
|
||||
var sc = tryGet(scriptsCache.get(path));
|
||||
if (sc.isPresent()) {
|
||||
return sc.get();
|
||||
}
|
||||
|
||||
try {
|
||||
var script = luaEngine.getScript(path, scriptType);
|
||||
if(script == null) {
|
||||
logger.error("Loading script {} failed! - {}", path, "script is null");
|
||||
return null;
|
||||
}
|
||||
scriptsCache.put(path, new SoftReference<>(script));
|
||||
return script;
|
||||
} catch (Exception e) {
|
||||
logger.error("Loading script {} failed! - {}", path, e.getLocalizedMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static SceneMeta getSceneMeta(int sceneId) {
|
||||
return tryGet(sceneMetaCache.get(sceneId)).orElseGet(() -> {
|
||||
var instance = SceneMeta.of(sceneId);
|
||||
sceneMetaCache.put(sceneId, new SoftReference<>(instance));
|
||||
return instance;
|
||||
});
|
||||
}
|
||||
|
||||
}
|
129
src/main/java/emu/grasscutter/scripts/ScriptLoaderLib.java
Normal file
129
src/main/java/emu/grasscutter/scripts/ScriptLoaderLib.java
Normal file
@ -0,0 +1,129 @@
|
||||
package emu.grasscutter.scripts;
|
||||
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.Loggers;
|
||||
import emu.grasscutter.utils.FileUtils;
|
||||
import lombok.Getter;
|
||||
import lombok.val;
|
||||
import org.anime_game_servers.gi_lua.models.loader.GIScriptLoader;
|
||||
import org.anime_game_servers.gi_lua.models.loader.ScriptSource;
|
||||
import org.anime_game_servers.jnlua_engine.JNLuaEngine;
|
||||
import org.anime_game_servers.lua.engine.LuaEngine;
|
||||
import org.anime_game_servers.lua.engine.LuaScript;
|
||||
import org.anime_game_servers.lua.engine.ScriptConfig;
|
||||
import org.anime_game_servers.lua.models.ScriptType;
|
||||
import org.anime_game_servers.luaj_engine.LuaJEngine;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class ScriptLoaderLib implements GIScriptLoader {
|
||||
private static final Logger logger = Loggers.getScriptSystem();
|
||||
/**
|
||||
* suggest GC to remove it if the memory is less
|
||||
*/
|
||||
private Map<Path, SoftReference<LuaScript>> scriptsCache = new ConcurrentHashMap<>();
|
||||
@Getter private LuaEngine luaEngine;
|
||||
|
||||
private ScriptConfig scriptConfig;
|
||||
|
||||
public ScriptLoaderLib() {
|
||||
this.scriptConfig = fromGcConfig();
|
||||
// Create script engine
|
||||
if(Grasscutter.getConfig().server.game.useJNLua){
|
||||
logger.info("Using JNLua");
|
||||
luaEngine = new JNLuaEngine(scriptConfig);
|
||||
} else {
|
||||
logger.info("Using LuaJ");
|
||||
luaEngine = new LuaJEngine(scriptConfig);
|
||||
}
|
||||
|
||||
addDefaultsForEngine(luaEngine);
|
||||
}
|
||||
|
||||
private ScriptConfig fromGcConfig(){
|
||||
val gcConfig = Grasscutter.getConfig();
|
||||
|
||||
return new ScriptConfig(this, false);
|
||||
}
|
||||
|
||||
public static <T> Optional<T> tryGet(SoftReference<T> softReference) {
|
||||
try {
|
||||
return Optional.ofNullable(softReference.get());
|
||||
}catch (NullPointerException npe) {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path getScriptPath(String scriptName) {
|
||||
var path = FileUtils.getScriptOverwritePath(scriptName);
|
||||
if(path != null && Files.exists(path)) {
|
||||
return path;
|
||||
}
|
||||
|
||||
path = FileUtils.getScriptPath(scriptName);
|
||||
if(path != null && Files.exists(path)) {
|
||||
return path;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public LuaScript getScript(@NotNull ScriptLoadParams scriptLoadParams) {
|
||||
val basePath = scriptLoadParams.getBasePath();
|
||||
val scriptPath = getScriptPath(basePath);
|
||||
if(scriptPath == null) {
|
||||
logger.error("Loading script {} failed! - {}", scriptLoadParams.getScriptName(), "scriptPath is null");
|
||||
return null;
|
||||
}
|
||||
var sc = tryGet(scriptsCache.get(scriptPath));
|
||||
if (sc.isPresent()) {
|
||||
return sc.get();
|
||||
}
|
||||
try {
|
||||
var script = luaEngine.getScript(scriptPath, scriptLoadParams.getScriptType());
|
||||
if(script == null) {
|
||||
logger.error("Loading script {} failed! - {}", scriptPath, "script is null");
|
||||
return null;
|
||||
}
|
||||
scriptsCache.put(scriptPath, new SoftReference<>(script));
|
||||
return script;
|
||||
} catch (Exception e) {
|
||||
logger.error("Loading script {} failed! - {}", scriptPath, e.getLocalizedMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public InputStream openScript(@NotNull ScriptLoadParams scriptLoadParams) {
|
||||
val basePath = scriptLoadParams.getBasePath();
|
||||
val scriptPath = getScriptPath(basePath);
|
||||
if(scriptPath == null) {
|
||||
logger.error("Loading script {} failed! - {}", scriptLoadParams.getScriptName(), "scriptPath is null");
|
||||
return null;
|
||||
}
|
||||
if (Files.exists(scriptPath)) {
|
||||
try {
|
||||
return Files.newInputStream(scriptPath);
|
||||
} catch (IOException e) {
|
||||
logger.error("[Lua] exception while reading file {}:", scriptPath, e);
|
||||
}
|
||||
} else {
|
||||
logger.warn("[Lua] trying to load non existent lua file {}", scriptPath);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
39
src/main/java/emu/grasscutter/scripts/ScriptSystem.java
Normal file
39
src/main/java/emu/grasscutter/scripts/ScriptSystem.java
Normal file
@ -0,0 +1,39 @@
|
||||
package emu.grasscutter.scripts;
|
||||
|
||||
import emu.grasscutter.scripts.scriptlib_handlers.ScriptLibControllerHandlerProvider;
|
||||
import emu.grasscutter.scripts.scriptlib_handlers.ScriptLibGroupHandlerProvider;
|
||||
import emu.grasscutter.server.game.BaseGameSystem;
|
||||
import emu.grasscutter.server.game.GameServer;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import lombok.Getter;
|
||||
import lombok.val;
|
||||
import org.anime_game_servers.gi_lua.models.scene.SceneMeta;
|
||||
import org.anime_game_servers.gi_lua.script_lib.ScriptLib;
|
||||
import org.anime_game_servers.gi_lua.script_lib.ScriptLibHandler;
|
||||
|
||||
public class ScriptSystem extends BaseGameSystem {
|
||||
@Getter private static final ScriptLoaderLib scriptLoader = new ScriptLoaderLib();
|
||||
Int2ObjectMap<SceneMeta> sceneMetaCache = new Int2ObjectOpenHashMap<>();
|
||||
|
||||
@Getter ScriptLibHandler scriptLibHandler = new emu.grasscutter.scripts.ScriptLibHandler();
|
||||
|
||||
@Getter
|
||||
ScriptLibControllerHandlerProvider scriptLibControllerHandlerProvider = new ScriptLibControllerHandlerProvider();
|
||||
|
||||
@Getter
|
||||
ScriptLibGroupHandlerProvider scriptLibGroupHandlerProvider = new ScriptLibGroupHandlerProvider();
|
||||
public ScriptSystem(GameServer server) {
|
||||
super(server);
|
||||
ScriptLib.staticHandler = new StaticScriptLibHandler();
|
||||
}
|
||||
|
||||
public SceneMeta getSceneMeta(int sceneId) {
|
||||
if(sceneMetaCache.containsKey(sceneId)){
|
||||
return sceneMetaCache.get(sceneId);
|
||||
}
|
||||
val meta = SceneMeta.of(sceneId, scriptLoader);
|
||||
sceneMetaCache.put(sceneId, meta);
|
||||
return meta;
|
||||
}
|
||||
}
|
@ -2,10 +2,9 @@ package emu.grasscutter.scripts;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import emu.grasscutter.scripts.lua_engine.LuaEngine;
|
||||
import emu.grasscutter.scripts.lua_engine.LuaTable;
|
||||
import emu.grasscutter.utils.Position;
|
||||
import lombok.val;
|
||||
import org.anime_game_servers.lua.engine.LuaTable;
|
||||
import org.luaj.vm2.LuaValue;
|
||||
|
||||
public class ScriptUtils {
|
||||
@ -23,21 +22,6 @@ public class ScriptUtils {
|
||||
return map;
|
||||
}
|
||||
|
||||
public static LuaTable posToLua(Position position, LuaEngine engine){
|
||||
var result = engine.createTable();
|
||||
if(position != null){
|
||||
result.set("x", position.getX());
|
||||
result.set("y", position.getY());
|
||||
result.set("z", position.getZ());
|
||||
} else {
|
||||
result.set("x", 0);
|
||||
result.set("y", 0);
|
||||
result.set("z", 0);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static Position luaToPos(LuaTable position){
|
||||
val result = new Position();
|
||||
if(position != null){
|
||||
|
@ -0,0 +1,33 @@
|
||||
package emu.grasscutter.scripts;
|
||||
|
||||
import emu.grasscutter.Loggers;
|
||||
import emu.grasscutter.game.props.EntityIdType;
|
||||
import lombok.Getter;
|
||||
import org.anime_game_servers.gi_lua.script_lib.LuaContext;
|
||||
import org.anime_game_servers.gi_lua.script_lib.handler.ScriptLibStaticHandler;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
public class StaticScriptLibHandler implements ScriptLibStaticHandler {
|
||||
@Getter
|
||||
private static final Logger logger = Loggers.getScriptSystem();
|
||||
@Override
|
||||
public void PrintLog(String msg) {
|
||||
logger.debug("[LUA] PrintLog: {}", msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int GetEntityType(int entityId) {
|
||||
return EntityIdType.fromEntityId(entityId).getType().getValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void PrintContextLog(LuaContext luaContext, String msg) {
|
||||
if(luaContext instanceof emu.grasscutter.scripts.lua_engine.GroupEventLuaContext){
|
||||
var group = ((emu.grasscutter.scripts.lua_engine.GroupEventLuaContext) luaContext).getCurrentGroup();
|
||||
logger.debug("[LUA] PrintContextLog {} {}", group.getGroupInfo().getId(), msg);
|
||||
return;
|
||||
} else {
|
||||
logger.debug("[LUA] PrintContextLog {}", msg);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,127 +0,0 @@
|
||||
package emu.grasscutter.scripts.constants;
|
||||
|
||||
public class EventType {
|
||||
public static final int EVENT_NONE = 0;
|
||||
/**
|
||||
* param1: monster.configId
|
||||
*/
|
||||
public static final int EVENT_ANY_MONSTER_DIE = 1;
|
||||
public static final int EVENT_ANY_GADGET_DIE = 2;
|
||||
public static final int EVENT_VARIABLE_CHANGE = 3;
|
||||
public static final int EVENT_ENTER_REGION = 4;
|
||||
public static final int EVENT_LEAVE_REGION = 5;
|
||||
public static final int EVENT_GADGET_CREATE = 6;
|
||||
public static final int EVENT_GADGET_STATE_CHANGE = 7;
|
||||
public static final int EVENT_DUNGEON_SETTLE = 8;
|
||||
public static final int EVENT_SELECT_OPTION = 9;
|
||||
public static final int EVENT_CLIENT_EXECUTE = 10;
|
||||
public static final int EVENT_ANY_MONSTER_LIVE = 11;
|
||||
public static final int EVENT_SPECIFIC_MONSTER_HP_CHANGE = 12;
|
||||
public static final int EVENT_CITY_LEVELUP_UNLOCK_DUNGEON_ENTRY = 13;
|
||||
public static final int EVENT_DUNGEON_BROADCAST_ONTIMER = 14;
|
||||
public static final int EVENT_TIMER_EVENT = 15;
|
||||
public static final int EVENT_CHALLENGE_SUCCESS = 16;
|
||||
public static final int EVENT_CHALLENGE_FAIL = 17;
|
||||
public static final int EVENT_SEAL_BATTLE_BEGIN = 18;
|
||||
public static final int EVENT_SEAL_BATTLE_END = 19;
|
||||
public static final int EVENT_GATHER = 20;
|
||||
public static final int EVENT_QUEST_FINISH = 21;
|
||||
public static final int EVENT_MONSTER_BATTLE = 22;
|
||||
public static final int EVENT_CITY_LEVELUP = 23;
|
||||
public static final int EVENT_CUTSCENE_END = 24;
|
||||
public static final int EVENT_AVATAR_NEAR_PLATFORM = 25; // also send by the client
|
||||
public static final int EVENT_PLATFORM_REACH_POINT = 26;
|
||||
public static final int EVENT_UNLOCK_TRANS_POINT = 27;
|
||||
public static final int EVENT_QUEST_START = 28;
|
||||
public static final int EVENT_GROUP_LOAD = 29;
|
||||
public static final int EVENT_GROUP_WILL_UNLOAD = 30;
|
||||
public static final int EVENT_GROUP_WILL_REFRESH = 31;
|
||||
public static final int EVENT_GROUP_REFRESH = 32;
|
||||
public static final int EVENT_DUNGEON_REWARD_GET = 33;
|
||||
public static final int EVENT_SPECIFIC_GADGET_HP_CHANGE = 34;
|
||||
public static final int EVENT_MONSTER_TIDE_OVER = 35;
|
||||
public static final int EVENT_MONSTER_TIDE_CREATE = 36;
|
||||
public static final int EVENT_MONSTER_TIDE_DIE = 37;
|
||||
public static final int EVENT_SEALAMP_PHASE_CHANGE = 38;
|
||||
public static final int EVENT_BLOSSOM_PROGRESS_FINISH = 39;
|
||||
public static final int EVENT_BLOSSOM_CHEST_DIE = 40;
|
||||
public static final int EVENT_GADGET_PLAY_START = 41;
|
||||
public static final int EVENT_GADGET_PLAY_START_CD = 42;
|
||||
public static final int EVENT_GADGET_PLAY_STOP = 43;
|
||||
public static final int EVENT_GADGET_LUA_NOTIFY = 44;
|
||||
public static final int EVENT_MP_PLAY_PREPARE = 45;
|
||||
public static final int EVENT_MP_PLAY_BATTLE = 46;
|
||||
public static final int EVENT_MP_PLAY_PREPARE_INTERRUPT = 47;
|
||||
public static final int EVENT_SELECT_DIFFICULTY = 48;
|
||||
public static final int EVENT_SCENE_MP_PLAY_BATTLE_STATE = 49;
|
||||
public static final int EVENT_SCENE_MP_PLAY_BATTLE_STAGE_CHANGE = 50;
|
||||
public static final int EVENT_SCENE_MP_PLAY_BATTLE_RESULT = 51;
|
||||
public static final int EVENT_SEAL_BATTLE_PROGRESS_DECREASE = 52;
|
||||
public static final int EVENT_GENERAL_REWARD_DIE = 53;
|
||||
public static final int EVENT_SCENE_MP_PLAY_BATTLE_INTERRUPT = 54;
|
||||
public static final int EVENT_MONSTER_DIE_BEFORE_LEAVE_SCENE = 55;
|
||||
public static final int EVENT_SCENE_MP_PLAY_OPEN = 56;
|
||||
public static final int EVENT_OFFERING_LEVELUP = 57;
|
||||
public static final int EVENT_DUNGEON_REVIVE = 58;
|
||||
public static final int EVENT_SCENE_MP_PLAY_ALL_AVATAR_DIE = 59;
|
||||
public static final int EVENT_DUNGEON_ALL_AVATAR_DIE = 60;
|
||||
public static final int EVENT_GENERAL_REWARD_TAKEN = 61;
|
||||
public static final int EVENT_PLATFORM_REACH_ARRAYPOINT = 62;
|
||||
public static final int EVENT_SCENE_MULTISTAGE_PLAY_STAGE_END = 63;
|
||||
public static final int EVENT_SCENE_MULTISTAGE_PLAY_END_STAGE_REQ = 64;
|
||||
public static final int EVENT_MECHANICUS_PICKED_CARD = 65;
|
||||
public static final int EVENT_POOL_MONSTER_TIDE_OVER = 66;
|
||||
public static final int EVENT_POOL_MONSTER_TIDE_CREATE = 67;
|
||||
public static final int EVENT_POOL_MONSTER_TIDE_DIE = 68;
|
||||
public static final int EVENT_DUNGEON_AVATAR_SLIP_DIE = 69;
|
||||
public static final int EVENT_GALLERY_START = 70;
|
||||
public static final int EVENT_GALLERY_STOP = 71;
|
||||
public static final int EVENT_TIME_AXIS_PASS = 72;
|
||||
public static final int EVENT_FLEUR_FAIR_DUNGEON_ALL_PLAYER_ENTER = 73;
|
||||
public static final int EVENT_GADGETTALK_DONE = 74;
|
||||
public static final int EVENT_SET_GAME_TIME = 75;
|
||||
public static final int EVENT_HIDE_AND_SEEK_PLAYER_QUIT = 76;
|
||||
public static final int EVENT_AVATAR_DIE = 77;
|
||||
public static final int EVENT_SCENE_MULTISTAGE_PLAY_STAGE_START = 78;
|
||||
public static final int EVENT_GALLERY_PROGRESS_PASS = 79;
|
||||
public static final int EVENT_GALLERY_PROGRESS_EMPTY = 80;
|
||||
public static final int EVENT_GALLERY_PROGRESS_FULL = 81;
|
||||
public static final int EVENT_HUNTING_FINISH_FINAL = 82;
|
||||
public static final int EVENT_USE_WIDGET_TOY_FOX_CAMERA = 83;
|
||||
public static final int EVENT_LUNA_RITE_SACRIFICE = 84;
|
||||
public static final int EVENT_SUMO_SWITCH_TEAM_EVENT = 85;
|
||||
public static final int EVENT_FISHING_START = 86;
|
||||
public static final int EVENT_FISHING_STOP = 87;
|
||||
public static final int EVENT_FISHING_QTE_FINISH = 88;
|
||||
public static final int EVENT_FISHING_TIMEOUT_FLEE = 89;
|
||||
public static final int EVENT_ROGUE_CELL_STATE_CHANGE = 90;
|
||||
public static final int EVENT_ROGUE_CELL_CONSTRUCT = 91;
|
||||
public static final int EVENT_ROGUE_CELL_FINISH_SELECT_CARD = 92;
|
||||
public static final int EVENT_ANY_MONSTER_CAPTURE = 93;
|
||||
public static final int EVENT_ACTIVITY_INTERACT_GADGET = 94;
|
||||
public static final int EVENT_CHALLENGE_PAUSE = 95;
|
||||
public static final int EVENT_LEVEL_TAG_CHANGE = 96;
|
||||
public static final int EVENT_CUSTOM_DUNGEON_START = 97;
|
||||
public static final int EVENT_CUSTOM_DUNGEON_RESTART = 98;
|
||||
public static final int EVENT_CUSTOM_DUNGEON_REACTIVE = 99;
|
||||
public static final int EVENT_CUSTOM_DUNGEON_OUT_STUCK = 100;
|
||||
public static final int EVENT_CUSTOM_DUNGEON_EXIT_TRY = 101;
|
||||
public static final int EVENT_CUSTOM_DUNGEON_OFFICIAL_RESTART = 102;
|
||||
public static final int EVENT_ANY_MONSTER_CAPTURE_AND_DISAPPEAR = 103;
|
||||
public static final int EVENT_MICHIAE_INTERACT = 104;
|
||||
public static final int EVENT_SELECT_UIINTERACT = 105;
|
||||
public static final int EVENT_LUA_NOTIFY = 106;
|
||||
public static final int EVENT_PHOTO_FINISH = 107;
|
||||
public static final int EVENT_IRODORI_MASTER_READY = 108;
|
||||
public static final int EVENT_ROGUE_START_FIGHT = 109;
|
||||
public static final int EVENT_ROGUE_CREAGE_FIGHT_GADGET = 110;
|
||||
public static final int EVENT_ROGUE_CREAGE_REPAIR_GADGET = 111;
|
||||
public static final int EVENT_ROGUE_OPEN_ACCESS = 112;
|
||||
public static final int EVENT_GADGET_GIVING_FINISHED = 113;
|
||||
public static final int EVENT_OBSERVATION_POINT_NOTIFY = 114;
|
||||
public static final int EVENT_GADGET_GIVING_TAKEBACK = 115;
|
||||
public static final int EVENT_ECHO_SHELL_INTERACT = 116;
|
||||
public static final int EVENT_PLATFORM_ARRIVAL = 2701;
|
||||
public static final int EVENT_PLAYER_BACK_GALLERY_REVIVE_POINT = 2800;
|
||||
public static final int EVENT_GALLERY_CANNOT_START_AFTER_COUNTDOWN = 2801;
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
package emu.grasscutter.scripts.constants;
|
||||
|
||||
public enum GroupKillPolicy {
|
||||
GROUP_KILL_NONE,
|
||||
GROUP_KILL_ALL,
|
||||
GROUP_KILL_MONSTER,
|
||||
GROUP_KILL_GADGET,
|
||||
GROUP_KILL_NPC
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
package emu.grasscutter.scripts.constants;
|
||||
|
||||
public interface IntValueEnum {
|
||||
int getValue();
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
package emu.grasscutter.scripts.constants;
|
||||
|
||||
public class ScriptGadgetState {
|
||||
public static final int Default = 0;
|
||||
public static final int GatherDrop = 1;
|
||||
public static final int ChestLocked = 101;
|
||||
public static final int ChestOpened = 102;
|
||||
public static final int ChestTrap = 103;
|
||||
public static final int ChestBramble = 104;
|
||||
public static final int ChestFrozen = 105;
|
||||
public static final int ChestRock = 106;
|
||||
public static final int GearStart = 201;
|
||||
public static final int GearStop = 202;
|
||||
public static final int GearAction1 = 203;
|
||||
public static final int GearAction2 = 204;
|
||||
public static final int CrystalResonate1 = 301;
|
||||
public static final int CrystalResonate2 = 302;
|
||||
public static final int CrystalExplode = 303;
|
||||
public static final int CrystalDrain = 304;
|
||||
public static final int StatueActive = 401;
|
||||
public static final int Action01 = 901;
|
||||
public static final int Action02 = 902;
|
||||
public static final int Action03 = 903;
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
package emu.grasscutter.scripts.constants;
|
||||
|
||||
public class ScriptRegionShape {
|
||||
public static final int NONE = 0;
|
||||
public static final int SPHERE = 1;
|
||||
public static final int CUBIC = 2;
|
||||
public static final int CYLINDER = 3;
|
||||
public static final int POLYGON = 4;
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
package emu.grasscutter.scripts.constants;
|
||||
|
||||
public enum SealBattleType {
|
||||
NONE,
|
||||
ENERGY_CHARGE,
|
||||
KILL_MONSTER
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
package emu.grasscutter.scripts.constants;
|
||||
|
||||
public enum VisionLevelType {
|
||||
VISION_LEVEL_NORMAL,
|
||||
VISION_LEVEL_LITTLE_REMOTE,
|
||||
VISION_LEVEL_REMOTE,
|
||||
VISION_LEVEL_SUPER,
|
||||
VISION_LEVEL_NEARBY,
|
||||
VISION_LEVEL_SUPER_NEARBY,
|
||||
VISION_LEVEL_SUPER_NUM,
|
||||
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
package emu.grasscutter.scripts.constants.temporary;
|
||||
|
||||
public enum ExhibitionPlayType {
|
||||
Challenge,
|
||||
Gallery,
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
package emu.grasscutter.scripts.constants.temporary;
|
||||
|
||||
public enum FlowSuiteOperatePolicy {
|
||||
DEFAULT,
|
||||
COMPLETE
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
package emu.grasscutter.scripts.constants.temporary;
|
||||
|
||||
public enum GalleryProgressScoreType {
|
||||
GALLERY_PROGRESS_SCORE_NONE,
|
||||
GALLERY_PROGRESS_SCORE_NO_DEGRADE
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
package emu.grasscutter.scripts.constants.temporary;
|
||||
|
||||
public enum GalleryProgressScoreUIType {
|
||||
GALLERY_PROGRESS_SCORE_UI_TYPE_NONE,
|
||||
GALLERY_PROGRESS_SCORE_UI_TYPE_BUOYANT_COMBAT,
|
||||
GALLERY_PROGRESS_SCORE_UI_TYPE_SUMO_STAGE,
|
||||
GALLERY_PROGRESS_SCORE_UI_TYPE_DIG,
|
||||
GALLERY_PROGRESS_SCORE_UI_TYPE_CRYSTAL_LINK,
|
||||
GALLERY_PROGRESS_SCORE_UI_TYPE_TREASURE;
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
package emu.grasscutter.scripts.data;
|
||||
|
||||
import emu.grasscutter.utils.Position;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class DummyPoint {
|
||||
private Position pos;
|
||||
private Position rot;
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
package emu.grasscutter.scripts.data;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class Explore {
|
||||
private String name;
|
||||
private int exp;
|
||||
}
|
@ -1,77 +0,0 @@
|
||||
package emu.grasscutter.scripts.data;
|
||||
|
||||
import com.github.davidmoten.rtreemulti.RTree;
|
||||
import com.github.davidmoten.rtreemulti.geometry.Geometry;
|
||||
import com.github.davidmoten.rtreemulti.geometry.Rectangle;
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.scripts.SceneIndexManager;
|
||||
import emu.grasscutter.scripts.ScriptLoader;
|
||||
import emu.grasscutter.scripts.lua_engine.ScriptType;
|
||||
import emu.grasscutter.utils.Position;
|
||||
import lombok.*;
|
||||
|
||||
import javax.script.Bindings;
|
||||
import javax.script.CompiledScript;
|
||||
import javax.script.ScriptException;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@ToString
|
||||
@Getter
|
||||
public class SceneBlock {
|
||||
@Setter(AccessLevel.PACKAGE)
|
||||
private int id;
|
||||
private Position max;
|
||||
private Position min;
|
||||
|
||||
private int sceneId;
|
||||
private Map<Integer,SceneGroup> groups;
|
||||
private RTree<SceneGroup, Geometry> sceneGroupIndex;
|
||||
|
||||
private transient boolean loaded; // Not an actual variable in the scripts either
|
||||
|
||||
public void setLoaded(boolean loaded) {
|
||||
this.loaded = loaded;
|
||||
}
|
||||
|
||||
public boolean contains(Position pos) {
|
||||
int range = Grasscutter.getConfig().server.game.loadEntitiesForPlayerRange;
|
||||
return pos.getX() <= (this.max.getX() + range) && pos.getX() >= (this.min.getX() - range) &&
|
||||
pos.getZ() <= (this.max.getZ() + range) && pos.getZ() >= (this.min.getZ() - range);
|
||||
}
|
||||
|
||||
public SceneBlock load(int sceneId) {
|
||||
if (this.loaded) {
|
||||
return this;
|
||||
}
|
||||
this.sceneId = sceneId;
|
||||
this.setLoaded(true);
|
||||
|
||||
val cs = ScriptLoader.getScript("Scene/" + sceneId + "/scene" + sceneId + "_block" + this.id + ".lua", ScriptType.DATA_STORAGE);
|
||||
|
||||
if (cs == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Eval script
|
||||
try {
|
||||
cs.evaluate();
|
||||
|
||||
// Set groups
|
||||
this.groups = cs.getGlobalVariableList("groups", SceneGroup.class).stream()
|
||||
.collect(Collectors.toMap(x -> x.getId(), y -> y, (a, b) -> a));
|
||||
|
||||
this.groups.values().forEach(g -> g.block_id = this.id);
|
||||
this.sceneGroupIndex = SceneIndexManager.buildIndex(3, this.groups.values(), g -> g.getPos().toPoint());
|
||||
} catch (ScriptException exception) {
|
||||
Grasscutter.getLogger().error("An error occurred while loading block " + this.id + " in scene " + sceneId, exception);
|
||||
}
|
||||
Grasscutter.getLogger().debug("Successfully loaded block {} in scene {}.", this.id, sceneId);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Rectangle toRectangle() {
|
||||
return Rectangle.create(this.min.toXZDoubleArray(), this.max.toXZDoubleArray());
|
||||
}
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
package emu.grasscutter.scripts.data;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
|
||||
@Getter
|
||||
@ToString
|
||||
public class SceneBossChest {
|
||||
private int life_time;
|
||||
private int monster_config_id;
|
||||
private int resin;
|
||||
private int take_num;
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
package emu.grasscutter.scripts.data;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
|
||||
@ToString
|
||||
@Getter
|
||||
public class SceneBusiness {
|
||||
private int type;
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
package emu.grasscutter.scripts.data;
|
||||
|
||||
import emu.grasscutter.utils.Position;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
|
||||
@ToString
|
||||
@Getter
|
||||
public class SceneConfig {
|
||||
private Position vision_anchor;
|
||||
private Position born_pos;
|
||||
private Position born_rot;
|
||||
private Position begin_pos;
|
||||
private Position size;
|
||||
private float die_y;
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
package emu.grasscutter.scripts.data;
|
||||
|
||||
import emu.grasscutter.game.props.EntityIdType;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ToString
|
||||
@Getter
|
||||
public class SceneGadget extends SceneObject{
|
||||
private int gadget_id;
|
||||
private int state;
|
||||
private int point_type;
|
||||
private SceneBossChest boss_chest;
|
||||
private int chest_drop_id;
|
||||
private int interact_id;
|
||||
private boolean isOneoff;
|
||||
private int draft_id;
|
||||
private int route_id;
|
||||
private boolean start_route = true;
|
||||
private boolean is_use_point_array = false;
|
||||
private boolean persistent = false;
|
||||
private boolean showcutscene;
|
||||
private Explore explore;
|
||||
private List<Integer> arguments;
|
||||
|
||||
public void setIsOneoff(boolean isOneoff) {
|
||||
this.isOneoff = isOneoff;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityIdType getType() {
|
||||
return EntityIdType.GADGET;
|
||||
}
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
package emu.grasscutter.scripts.data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
|
||||
@ToString
|
||||
@Getter
|
||||
public class SceneGarbage {
|
||||
private List<SceneGadget> gadgets;
|
||||
}
|
@ -1,190 +0,0 @@
|
||||
package emu.grasscutter.scripts.data;
|
||||
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.data.GameData;
|
||||
import emu.grasscutter.game.world.GroupReplacementData;
|
||||
import emu.grasscutter.scripts.ScriptLoader;
|
||||
import emu.grasscutter.scripts.lua_engine.LuaScript;
|
||||
import emu.grasscutter.scripts.lua_engine.ScriptType;
|
||||
import emu.grasscutter.utils.Position;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
import lombok.val;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@ToString
|
||||
@Getter
|
||||
public class SceneGroup {
|
||||
public transient int block_id; // Not an actual variable in the scripts but we will keep it here for reference
|
||||
|
||||
@Setter
|
||||
private int id;
|
||||
private int refresh_id;
|
||||
@Nullable
|
||||
private Position pos;
|
||||
|
||||
@Nullable
|
||||
private Map<Integer, SceneMonster> monsters; // <ConfigId, Monster>
|
||||
@Nullable
|
||||
private Map<Integer, SceneNPC> npcs; // <ConfigId, Npc>
|
||||
@Nullable
|
||||
private Map<Integer, SceneGadget> gadgets; // <ConfigId, Gadgets>
|
||||
@Nullable
|
||||
private Map<String, SceneTrigger> triggers;
|
||||
@Nullable
|
||||
private Map<Integer, SceneRegion> regions;
|
||||
@Nullable
|
||||
private List<SceneSuite> suites;
|
||||
@Nullable
|
||||
private List<SceneVar> variables;
|
||||
|
||||
@Nullable
|
||||
private SceneBusiness business;
|
||||
@Nullable
|
||||
private SceneGarbage garbages;
|
||||
@Nullable
|
||||
private SceneInitConfig init_config;
|
||||
private final boolean dynamic_load = false;
|
||||
|
||||
@Nullable
|
||||
private SceneReplaceable is_replaceable;
|
||||
|
||||
private transient boolean loaded; // Not an actual variable in the scripts either
|
||||
private transient LuaScript script;
|
||||
|
||||
public static SceneGroup of(int groupId) {
|
||||
var group = new SceneGroup();
|
||||
group.id = groupId;
|
||||
return group;
|
||||
}
|
||||
|
||||
public int getBusinessType() {
|
||||
return this.business == null ? 0 : this.business.getType();
|
||||
}
|
||||
|
||||
public List<SceneGadget> getGarbageGadgets() {
|
||||
return this.garbages == null ? null : this.garbages.getGadgets();
|
||||
}
|
||||
|
||||
public boolean isReplaceable() {
|
||||
return this.is_replaceable != null ? this.is_replaceable.isValue() : false;
|
||||
}
|
||||
|
||||
public SceneSuite getSuiteByIndex(int index) {
|
||||
if (index < 1 || index > suites.size()) {
|
||||
return null;
|
||||
}
|
||||
return this.suites.get(index - 1);
|
||||
}
|
||||
|
||||
public synchronized SceneGroup load(int sceneId) {
|
||||
if (this.loaded) {
|
||||
return this;
|
||||
}
|
||||
// Set flag here so if there is no script, we don't call this function over and over again.
|
||||
this.loaded = true;
|
||||
|
||||
val cs = ScriptLoader.getScript("Scene/" + sceneId + "/scene" + sceneId + "_group" + this.id + ".lua", ScriptType.EXECUTABLE);
|
||||
|
||||
if (cs == null) {
|
||||
return this;
|
||||
}
|
||||
|
||||
this.script = cs;
|
||||
|
||||
// Eval script
|
||||
try {
|
||||
cs.evaluate();
|
||||
|
||||
// Set
|
||||
this.monsters = cs.getGlobalVariableList("monsters", SceneMonster.class).stream()
|
||||
.collect(Collectors.toMap(x -> x.config_id, y -> y, (a, b) -> a));
|
||||
this.monsters.values().forEach(m -> m.group = this);
|
||||
|
||||
this.npcs = cs.getGlobalVariableList("npcs", SceneNPC.class).stream()
|
||||
.collect(Collectors.toMap(x -> x.config_id, y -> y, (a, b) -> a));
|
||||
this.npcs.values().forEach(m -> m.group = this);
|
||||
|
||||
this.gadgets = cs.getGlobalVariableList("gadgets", SceneGadget.class).stream()
|
||||
.collect(Collectors.toMap(x -> x.config_id, y -> y, (a, b) -> a));
|
||||
this.gadgets.values().forEach(m -> m.group = this);
|
||||
|
||||
this.triggers = cs.getGlobalVariableList("triggers", SceneTrigger.class).stream()
|
||||
.collect(Collectors.toMap(SceneTrigger::getName, y -> y, (a, b) -> a));
|
||||
this.triggers.values().forEach(t -> t.setCurrentGroup(this));
|
||||
|
||||
this.suites = cs.getGlobalVariableList("suites", SceneSuite.class);
|
||||
this.regions = cs.getGlobalVariableList("regions", SceneRegion.class).stream()
|
||||
.collect(Collectors.toMap(x -> x.config_id, y -> y, (a, b) -> a));
|
||||
this.regions.values().forEach(m -> m.group = this);
|
||||
|
||||
this.init_config = cs.getGlobalVariable("init_config", SceneInitConfig.class);
|
||||
|
||||
// Garbages // TODO: fix properly later
|
||||
/*Object garbagesValue = this.bindings.get("garbages");
|
||||
if (garbagesValue instanceof LuaValue garbagesTable) {
|
||||
this.garbages = new SceneGarbage();
|
||||
if (garbagesTable.checktable().get("gadgets") != LuaValue.NIL) {
|
||||
this.garbages.gadgets = ScriptLoader.getSerializer().toList(SceneGadget.class, garbagesTable.checktable().get("gadgets").checktable());
|
||||
this.garbages.gadgets.forEach(m -> m.group = this);
|
||||
}
|
||||
}*/
|
||||
|
||||
// Add variables to suite
|
||||
this.variables = cs.getGlobalVariableList("variables", SceneVar.class);
|
||||
|
||||
// Add monsters and gadgets to suite
|
||||
this.suites.forEach(i -> i.init(this));
|
||||
|
||||
} catch (Exception e) {
|
||||
Grasscutter.getLogger().error("An error occurred while loading group " + this.id + " in scene " + sceneId + ".", e);
|
||||
}
|
||||
|
||||
Grasscutter.getLogger().debug("Successfully loaded group {} in scene {}.", this.id, sceneId);
|
||||
return this;
|
||||
}
|
||||
|
||||
public int findInitSuiteIndex(int exclude_index) { //TODO: Investigate end index
|
||||
if (init_config == null) return 1;
|
||||
if (init_config.getIo_type() == 1) return init_config.getSuite(); //IO TYPE FLOW
|
||||
if (init_config.isRand_suite()) {
|
||||
if (suites.size() == 1) {
|
||||
return init_config.getSuite();
|
||||
} else {
|
||||
List<Integer> randSuiteList = new ArrayList<>();
|
||||
for (int i = 0; i < suites.size(); i++) {
|
||||
if (i == exclude_index) continue;
|
||||
|
||||
var suite = suites.get(i);
|
||||
for (int j = 0; j < suite.getRand_weight(); j++) randSuiteList.add(Integer.valueOf(i + 1));
|
||||
}
|
||||
return randSuiteList.get(new Random().nextInt(randSuiteList.size()));
|
||||
}
|
||||
}
|
||||
return init_config.getSuite();
|
||||
}
|
||||
|
||||
public Optional<SceneBossChest> searchBossChestInGroup() {
|
||||
return this.gadgets.values().stream().map(g -> g.getBoss_chest()).filter(Objects::nonNull)
|
||||
.filter(bossChest -> bossChest.getMonster_config_id() > 0)
|
||||
.findFirst();
|
||||
}
|
||||
|
||||
public List<SceneGroup> getReplaceableGroups(Collection<SceneGroup> loadedGroups) {
|
||||
return this.is_replaceable == null ? List.of() :
|
||||
Optional.ofNullable(GameData.getGroupReplacements().get(this.id)).stream()
|
||||
.map(GroupReplacementData::getReplace_groups)
|
||||
.flatMap(List::stream)
|
||||
.map(replacementId -> loadedGroups.stream().filter(g -> g.id == replacementId).findFirst())
|
||||
.filter(Optional::isPresent).map(Optional::get)
|
||||
.filter(replacementGroup -> replacementGroup.is_replaceable != null)
|
||||
.filter(replacementGroup -> (replacementGroup.is_replaceable.isValue()
|
||||
&& replacementGroup.is_replaceable.getVersion() <= this.is_replaceable.getVersion())
|
||||
|| replacementGroup.is_replaceable.isNew_bin_only())
|
||||
.toList();
|
||||
}
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
package emu.grasscutter.scripts.data;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
|
||||
@ToString
|
||||
@Getter
|
||||
public class SceneInitConfig {
|
||||
private int suite;
|
||||
private int end_suite;
|
||||
private int io_type ;
|
||||
private boolean rand_suite;
|
||||
}
|
@ -1,73 +0,0 @@
|
||||
package emu.grasscutter.scripts.data;
|
||||
|
||||
import com.github.davidmoten.rtreemulti.RTree;
|
||||
import com.github.davidmoten.rtreemulti.geometry.Geometry;
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.scripts.SceneIndexManager;
|
||||
import emu.grasscutter.scripts.ScriptLoader;
|
||||
import emu.grasscutter.scripts.lua_engine.LuaScript;
|
||||
import emu.grasscutter.scripts.lua_engine.ScriptType;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
import lombok.val;
|
||||
|
||||
import javax.script.Bindings;
|
||||
import javax.script.CompiledScript;
|
||||
import javax.script.ScriptException;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@ToString
|
||||
@Getter
|
||||
public class SceneMeta {
|
||||
|
||||
private SceneConfig config;
|
||||
private Map<Integer, SceneBlock> blocks;
|
||||
|
||||
private LuaScript context;
|
||||
|
||||
private RTree<SceneBlock, Geometry> sceneBlockIndex;
|
||||
|
||||
public static SceneMeta of(int sceneId) {
|
||||
return new SceneMeta().load(sceneId);
|
||||
}
|
||||
|
||||
public SceneMeta load(int sceneId) {
|
||||
// Get compiled script if cached
|
||||
val cs = ScriptLoader.getScript("Scene/" + sceneId + "/scene" + sceneId + ".lua", ScriptType.DATA_STORAGE);
|
||||
|
||||
if (cs == null) {
|
||||
Grasscutter.getLogger().warn("No script found for scene " + sceneId);
|
||||
return null;
|
||||
}
|
||||
|
||||
// Eval script
|
||||
try {
|
||||
cs.evaluate();
|
||||
|
||||
this.config = cs.getGlobalVariable("scene_config", SceneConfig.class);
|
||||
|
||||
// TODO optimize later
|
||||
// Create blocks
|
||||
List<Integer> blockIds = cs.getGlobalVariableList("blocks", Integer.class);
|
||||
List<SceneBlock> blocks = cs.getGlobalVariableList("block_rects", SceneBlock.class);
|
||||
|
||||
for (int i = 0; i < blocks.size(); i++) {
|
||||
SceneBlock block = blocks.get(i);
|
||||
block.setId(blockIds.get(i));
|
||||
}
|
||||
|
||||
this.blocks = blocks.stream().collect(Collectors.toMap(b -> b.getId(), b -> b, (a, b) -> a));
|
||||
this.sceneBlockIndex = SceneIndexManager.buildIndex(2, blocks, SceneBlock::toRectangle);
|
||||
|
||||
} catch (ScriptException exception) {
|
||||
Grasscutter.getLogger().error("An error occurred while running a script.", exception);
|
||||
return null;
|
||||
}
|
||||
Grasscutter.getLogger().debug("Successfully loaded metadata in scene {}.", sceneId);
|
||||
return this;
|
||||
}
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
package emu.grasscutter.scripts.data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import emu.grasscutter.game.props.EntityIdType;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ToString
|
||||
@Getter
|
||||
public class SceneMonster extends SceneObject{
|
||||
private int monster_id;
|
||||
private int pose_id;
|
||||
private String pose_logic_state;
|
||||
private int drop_id;
|
||||
private boolean disableWander;
|
||||
private int title_id;
|
||||
private int special_name_id;
|
||||
private List<Integer> affix;
|
||||
private boolean isElite;
|
||||
private int climate_area_id;
|
||||
private int ai_config_id;
|
||||
private int kill_score;
|
||||
private int speed_level;
|
||||
private long tag;
|
||||
private boolean is_light_config;
|
||||
|
||||
@Override
|
||||
public EntityIdType getType() {
|
||||
return EntityIdType.MONSTER;
|
||||
}
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
package emu.grasscutter.scripts.data;
|
||||
|
||||
import emu.grasscutter.game.props.EntityIdType;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
|
||||
@ToString
|
||||
@Getter
|
||||
public class SceneNPC extends SceneObject{
|
||||
private int npc_id;
|
||||
|
||||
@Override
|
||||
public EntityIdType getType() {
|
||||
return EntityIdType.NPC;
|
||||
}
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
package emu.grasscutter.scripts.data;
|
||||
|
||||
import emu.grasscutter.game.props.EntityIdType;
|
||||
import emu.grasscutter.game.props.EntityType;
|
||||
import emu.grasscutter.utils.Position;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
|
||||
@ToString
|
||||
@Getter
|
||||
public abstract class SceneObject {
|
||||
protected int level;
|
||||
protected int config_id;
|
||||
protected int area_id;
|
||||
protected int vision_level = 0;
|
||||
protected int mark_flag;
|
||||
protected String drop_tag;
|
||||
protected int guest_ban_drop;
|
||||
protected int oneoff_reset_version;
|
||||
protected int sight_group_index;
|
||||
// server_global_value_config, might be group only
|
||||
|
||||
protected Position pos;
|
||||
protected Position rot;
|
||||
/**
|
||||
* not set by lua
|
||||
*/
|
||||
protected transient SceneGroup group;
|
||||
|
||||
public abstract EntityIdType getType();
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user