mirror of
https://github.com/Grasscutters/Grasscutter.git
synced 2025-12-23 04:15:49 +01:00
Merge pull request Grasscutter-Quests#53
'Updated with how talks are handle' by `mjolsic`
This commit is contained in:
63
src/main/java/emu/grasscutter/game/talk/TalkExec.java
Normal file
63
src/main/java/emu/grasscutter/game/talk/TalkExec.java
Normal file
@@ -0,0 +1,63 @@
|
||||
package emu.grasscutter.game.talk;
|
||||
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@AllArgsConstructor
|
||||
public enum TalkExec {
|
||||
TALK_EXEC_NONE(0),
|
||||
TALK_EXEC_SET_GADGET_STATE(1),
|
||||
TALK_EXEC_SET_GAME_TIME(2),
|
||||
TALK_EXEC_NOTIFY_GROUP_LUA(3),
|
||||
TALK_EXEC_SET_DAILY_TASK_VAR(4),
|
||||
TALK_EXEC_INC_DAILY_TASK_VAR(5),
|
||||
TALK_EXEC_DEC_DAILY_TASK_VAR(6),
|
||||
TALK_EXEC_SET_QUEST_VAR(7),
|
||||
TALK_EXEC_INC_QUEST_VAR(8),
|
||||
TALK_EXEC_DEC_QUEST_VAR(9),
|
||||
TALK_EXEC_SET_QUEST_GLOBAL_VAR(10),
|
||||
TALK_EXEC_INC_QUEST_GLOBAL_VAR(11),
|
||||
TALK_EXEC_DEC_QUEST_GLOBAL_VAR(12),
|
||||
TALK_EXEC_TRANS_SCENE_DUMMY_POINT(13),
|
||||
TALK_EXEC_SAVE_TALK_ID(14);
|
||||
|
||||
private static final Int2ObjectMap<TalkExec> execMap = new Int2ObjectOpenHashMap<>();
|
||||
private static final Map<String, TalkExec> execStringMap = new HashMap<>();
|
||||
|
||||
static {
|
||||
Stream.of(TalkExec.values())
|
||||
.filter(e -> e.name().startsWith("TALK_EXEC_"))
|
||||
.forEach(entry -> {
|
||||
execMap.put(entry.getValue(), entry);
|
||||
execStringMap.put(entry.name(), entry);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the talk execution condition by its value.
|
||||
*
|
||||
* @param value The integer value of the condition.
|
||||
* @return The corresponding enum value.
|
||||
*/
|
||||
public static TalkExec getExecByValue(int value) {
|
||||
return execMap.getOrDefault(value, TALK_EXEC_NONE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the talk execution by its name.
|
||||
*
|
||||
* @param name The string name of the condition.
|
||||
* @return The corresponding enum value.
|
||||
*/
|
||||
public static TalkExec getExecByName(String name) {
|
||||
return execStringMap.getOrDefault(name, TALK_EXEC_NONE);
|
||||
}
|
||||
|
||||
@Getter private final int value;
|
||||
}
|
||||
14
src/main/java/emu/grasscutter/game/talk/TalkExecHandler.java
Normal file
14
src/main/java/emu/grasscutter/game/talk/TalkExecHandler.java
Normal file
@@ -0,0 +1,14 @@
|
||||
package emu.grasscutter.game.talk;
|
||||
|
||||
import emu.grasscutter.data.excels.TalkConfigData;
|
||||
import emu.grasscutter.data.excels.TalkConfigData.TalkExecParam;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
|
||||
public abstract class TalkExecHandler {
|
||||
/**
|
||||
* @param player The player who is talking.
|
||||
* @param talkData The data associated with the talk.
|
||||
* @param execParam The execution parameter for the talk.
|
||||
*/
|
||||
public abstract void execute(Player player, TalkConfigData talkData, TalkExecParam execParam);
|
||||
}
|
||||
52
src/main/java/emu/grasscutter/game/talk/TalkManager.java
Normal file
52
src/main/java/emu/grasscutter/game/talk/TalkManager.java
Normal file
@@ -0,0 +1,52 @@
|
||||
package emu.grasscutter.game.talk;
|
||||
|
||||
import emu.grasscutter.data.GameData;
|
||||
import emu.grasscutter.data.binout.MainQuestData.TalkData;
|
||||
import emu.grasscutter.game.player.BasePlayerManager;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
|
||||
import lombok.NonNull;
|
||||
|
||||
import static emu.grasscutter.game.quest.enums.QuestContent.QUEST_CONTENT_COMPLETE_ANY_TALK;
|
||||
import static emu.grasscutter.game.quest.enums.QuestContent.QUEST_CONTENT_COMPLETE_TALK;
|
||||
import static emu.grasscutter.game.quest.enums.QuestCond.QUEST_COND_COMPLETE_TALK;
|
||||
|
||||
public final class TalkManager extends BasePlayerManager {
|
||||
public TalkManager(@NonNull Player player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked when a talk is triggered.
|
||||
*
|
||||
* @param talkId The ID of the talk.
|
||||
*/
|
||||
public void triggerTalkAction(int talkId) {
|
||||
var talkData = GameData.getTalkConfigDataMap().get(talkId);
|
||||
if (talkData == null || talkData.getFinishExec().isEmpty()) return;
|
||||
|
||||
var player = this.getPlayer();
|
||||
// Execute the talk action on associated handlers.
|
||||
talkData.getFinishExec().forEach(e -> this.getPlayer().getServer()
|
||||
.getTalkSystem().triggerExec(getPlayer(), talkData, e));
|
||||
|
||||
// Invoke the talking events for quests.
|
||||
var questManager = player.getQuestManager();
|
||||
questManager.queueEvent(QUEST_CONTENT_COMPLETE_ANY_TALK, talkId);
|
||||
questManager.queueEvent(QUEST_CONTENT_COMPLETE_TALK, talkId);
|
||||
questManager.queueEvent(QUEST_COND_COMPLETE_TALK, talkId);
|
||||
|
||||
// Save the talk value to the quest's data.
|
||||
this.saveTalkToQuest(talkId, talkData.getQuestId());
|
||||
}
|
||||
|
||||
public void saveTalkToQuest(int talkId, int mainQuestId) {
|
||||
// TODO, problem with this is that some talks for activity also have
|
||||
// quest id, which isn't present in QuestExcels
|
||||
var mainQuest = this.getPlayer().getQuestManager()
|
||||
.getMainQuestById(mainQuestId);
|
||||
if (mainQuest == null) return;
|
||||
|
||||
mainQuest.getTalks().put(talkId, new TalkData(talkId, ""));
|
||||
}
|
||||
}
|
||||
81
src/main/java/emu/grasscutter/game/talk/TalkSystem.java
Normal file
81
src/main/java/emu/grasscutter/game/talk/TalkSystem.java
Normal file
@@ -0,0 +1,81 @@
|
||||
package emu.grasscutter.game.talk;
|
||||
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.data.excels.TalkConfigData;
|
||||
import emu.grasscutter.data.excels.TalkConfigData.TalkExecParam;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
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 org.reflections.Reflections;
|
||||
|
||||
public final class TalkSystem extends BaseGameSystem {
|
||||
private final Int2ObjectMap<TalkExecHandler> execHandlers
|
||||
= new Int2ObjectOpenHashMap<>();
|
||||
|
||||
public TalkSystem(GameServer server) {
|
||||
super(server);
|
||||
|
||||
this.registerHandlers(this.execHandlers,
|
||||
"emu.grasscutter.game.talk.exec",
|
||||
TalkExecHandler.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers all handlers with the required conditions.
|
||||
*
|
||||
* @param map The map to save handlers to.
|
||||
* @param packageName The full package domain.
|
||||
* @param clazz The class which handlers should derive from.
|
||||
*/
|
||||
public <T> void registerHandlers(Int2ObjectMap<T> map, String packageName, Class<T> clazz) {
|
||||
var reflections = new Reflections(packageName);
|
||||
var handlerClasses = reflections.getSubTypesOf(clazz);
|
||||
|
||||
for (var obj : handlerClasses) {
|
||||
this.registerTalkHandler(map, obj);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the talk handler of the specified class.
|
||||
*
|
||||
* @param map The map to save the handler to.
|
||||
* @param handlerClass The class of the handler.
|
||||
*/
|
||||
public <T> void registerTalkHandler(Int2ObjectMap<T> map, Class<? extends T> handlerClass) {
|
||||
try {
|
||||
var value = 0; if (handlerClass.isAnnotationPresent(TalkValueExec.class)) {
|
||||
TalkValueExec opcode = handlerClass.getAnnotation(TalkValueExec.class);
|
||||
value = opcode.value().getValue();
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
if (value <= 0) return;
|
||||
map.put(value, handlerClass.getDeclaredConstructor().newInstance());
|
||||
} catch (Exception exception) {
|
||||
Grasscutter.getLogger().debug("Unable to register talk handler.", exception);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies the associated handler of a talk being triggered.
|
||||
*
|
||||
* @param player The player which triggered the talk.
|
||||
* @param talkData The data associated with the talk.
|
||||
* @param execParam The talk parameter.
|
||||
*/
|
||||
public void triggerExec(Player player, TalkConfigData talkData, TalkExecParam execParam) {
|
||||
var handler = this.execHandlers.get(execParam.getType().getValue());
|
||||
if (handler == null) {
|
||||
Grasscutter.getLogger().debug("Could not execute talk handlers for {} ({}).",
|
||||
talkData.getId(), execParam.getType().getValue());
|
||||
return;
|
||||
}
|
||||
|
||||
// Execute the handler.
|
||||
handler.execute(player, talkData, execParam);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package emu.grasscutter.game.talk;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface TalkValueExec {
|
||||
TalkExec value();
|
||||
}
|
||||
Reference in New Issue
Block a user