Commit 1de402bd authored by KingRainbow44's avatar KingRainbow44
Browse files

Merge branch 'development' into more-events

parents b9b4b6f4 f25fb629
package emu.grasscutter.game.quest.content;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValue;
import emu.grasscutter.game.quest.enums.QuestTrigger;
import emu.grasscutter.game.quest.handlers.QuestBaseHandler;
@QuestValue(QuestTrigger.QUEST_CONTENT_QUEST_STATE_NOT_EQUAL)
public class ContentQuestStateNotEqual extends QuestBaseHandler {
@Override
public boolean execute(GameQuest quest, QuestData.QuestCondition condition, String paramStr, int... params) {
GameQuest checkQuest = quest.getOwner().getQuestManager().getQuestById(params[0]);
if (checkQuest != null) {
return checkQuest.getState().getValue() != params[1];
}
return false;
}
}
\ No newline at end of file
package emu.grasscutter.game.quest.content;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValue;
import emu.grasscutter.game.quest.enums.QuestTrigger;
import emu.grasscutter.game.quest.handlers.QuestBaseHandler;
@QuestValue(QuestTrigger.QUEST_CONTENT_QUEST_VAR_EQUAL)
public class ContentQuestVarEqual extends QuestBaseHandler {
@Override
public boolean execute(GameQuest quest, QuestData.QuestCondition condition, String paramStr, int... params) {
int questVarValue = quest.getMainQuest().getQuestVars()[params[0]];
Grasscutter.getLogger().debug("questVar {} : {}", params[0],questVarValue);
return questVarValue == params[1];
}
}
package emu.grasscutter.game.quest.content;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValue;
import emu.grasscutter.game.quest.enums.QuestTrigger;
import emu.grasscutter.game.quest.handlers.QuestBaseHandler;
@QuestValue(QuestTrigger.QUEST_CONTENT_QUEST_VAR_GREATER)
public class ContentQuestVarGreater extends QuestBaseHandler {
@Override
public boolean execute(GameQuest quest, QuestData.QuestCondition condition, String paramStr, int... params) {
int questVarValue = quest.getMainQuest().getQuestVars()[params[0]];
Grasscutter.getLogger().debug("questVar {} : {}", params[0],questVarValue);
return questVarValue > params[1];
}
}
package emu.grasscutter.game.quest.content;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValue;
import emu.grasscutter.game.quest.enums.QuestTrigger;
import emu.grasscutter.game.quest.handlers.QuestBaseHandler;
@QuestValue(QuestTrigger.QUEST_CONTENT_QUEST_VAR_LESS)
public class ContentQuestVarLess extends QuestBaseHandler {
@Override
public boolean execute(GameQuest quest, QuestData.QuestCondition condition, String paramStr, int... params) {
int questVarValue = quest.getMainQuest().getQuestVars()[params[0]];
Grasscutter.getLogger().debug("questVar {} : {}", params[0],questVarValue);
return questVarValue < params[1];
}
}
package emu.grasscutter.game.quest.content;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.GameData;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.data.excels.TriggerExcelConfigData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValue;
import emu.grasscutter.game.quest.enums.QuestTrigger;
import emu.grasscutter.game.quest.handlers.QuestBaseHandler;
@QuestValue(QuestTrigger.QUEST_CONTENT_TRIGGER_FIRE)
public class ContentTriggerFire extends QuestBaseHandler {
@Override
public boolean execute(GameQuest quest, QuestData.QuestCondition condition, String paramStr, int... params) {
if(quest.getTriggers().containsKey(quest.getTriggerNameById(params[0]))) {
//We don't want to put a new key here
return quest.getTriggers().get(quest.getTriggerNameById(params[0]));
} else {
Grasscutter.getLogger().error("quest {} doesn't have trigger {}", quest.getSubQuestId(), params[0]);
return false;
}
}
}
package emu.grasscutter.game.quest.content;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValue;
import emu.grasscutter.game.quest.enums.QuestTrigger;
import emu.grasscutter.game.quest.handlers.QuestBaseHandler;
@QuestValue(QuestTrigger.QUEST_CONTENT_UNLOCK_TRANS_POINT)
public class ContentUnlockTransPoint extends QuestBaseHandler {
@Override
public boolean execute(GameQuest quest, QuestData.QuestCondition condition, String paramStr, int... params) {
return true;
}
}
...@@ -5,7 +5,14 @@ public enum QuestState { ...@@ -5,7 +5,14 @@ public enum QuestState {
QUEST_STATE_UNSTARTED (1), QUEST_STATE_UNSTARTED (1),
QUEST_STATE_UNFINISHED (2), QUEST_STATE_UNFINISHED (2),
QUEST_STATE_FINISHED (3), QUEST_STATE_FINISHED (3),
QUEST_STATE_FAILED (4); QUEST_STATE_FAILED (4),
// Used by lua
NONE (0),
UNSTARTED(1),
UNFINISHED(2),
FINISHED(3),
FAILED(4);
private final int value; private final int value;
......
package emu.grasscutter.game.quest.exec;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValue;
import emu.grasscutter.game.quest.enums.QuestTrigger;
import emu.grasscutter.game.quest.handlers.QuestExecHandler;
@QuestValue(QuestTrigger.QUEST_EXEC_DEC_QUEST_GLOBAL_VAR)
public class ExecDecQuestGlobalVar extends QuestExecHandler {
@Override
public boolean execute(GameQuest quest, QuestData.QuestExecParam condition, String... paramStr) {
quest.getOwner().getQuestManager().decQuestGlobalVarValue(Integer.valueOf(paramStr[0]),Integer.valueOf(paramStr[1]));
return true;
}
}
package emu.grasscutter.game.quest.exec;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValue;
import emu.grasscutter.game.quest.enums.QuestTrigger;
import emu.grasscutter.game.quest.handlers.QuestExecHandler;
@QuestValue(QuestTrigger.QUEST_EXEC_DEC_QUEST_VAR)
public class ExecDecQuestVar extends QuestExecHandler {
@Override
public boolean execute(GameQuest quest, QuestData.QuestExecParam condition, String... paramStr) {
quest.getMainQuest().decQuestVar(Integer.parseInt(paramStr[0]), Integer.parseInt(paramStr[1]));
return true;
}
}
package emu.grasscutter.game.quest.exec;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValue;
import emu.grasscutter.game.quest.enums.QuestTrigger;
import emu.grasscutter.game.quest.handlers.QuestExecHandler;
@QuestValue(QuestTrigger.QUEST_EXEC_INC_QUEST_GLOBAL_VAR)
public class ExecIncQuestGlobalVar extends QuestExecHandler {
@Override
public boolean execute(GameQuest quest, QuestData.QuestExecParam condition, String... paramStr) {
quest.getOwner().getQuestManager().incQuestGlobalVarValue(Integer.valueOf(paramStr[0]),Integer.valueOf(paramStr[1]));
return true;
}
}
\ No newline at end of file
package emu.grasscutter.game.quest.exec;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValue;
import emu.grasscutter.game.quest.enums.QuestTrigger;
import emu.grasscutter.game.quest.handlers.QuestExecHandler;
@QuestValue(QuestTrigger.QUEST_EXEC_INC_QUEST_VAR)
public class ExecIncQuestVar extends QuestExecHandler {
@Override
public boolean execute(GameQuest quest, QuestData.QuestExecParam condition, String... paramStr) {
quest.getMainQuest().incQuestVar(Integer.parseInt(paramStr[0]), Integer.parseInt(paramStr[1]));
return true;
}
}
package emu.grasscutter.game.quest.exec;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValue;
import emu.grasscutter.game.quest.enums.QuestTrigger;
import emu.grasscutter.game.quest.handlers.QuestExecHandler;
@QuestValue(QuestTrigger.QUEST_EXEC_SET_QUEST_GLOBAL_VAR)
public class ExecSetQuestGlobalVar extends QuestExecHandler {
@Override
public boolean execute(GameQuest quest, QuestData.QuestExecParam condition, String... paramStr) {
quest.getOwner().getQuestManager().setQuestGlobalVarValue(Integer.valueOf(paramStr[0]),Integer.valueOf(paramStr[1]));
return true;
}
}
package emu.grasscutter.game.quest.exec;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.QuestValue;
import emu.grasscutter.game.quest.enums.QuestTrigger;
import emu.grasscutter.game.quest.handlers.QuestExecHandler;
@QuestValue(QuestTrigger.QUEST_EXEC_SET_QUEST_VAR)
public class ExecSetQuestVar extends QuestExecHandler {
@Override
public boolean execute(GameQuest quest, QuestData.QuestExecParam condition, String... paramStr) {
quest.getMainQuest().setQuestVar(Integer.parseInt(paramStr[0]), Integer.parseInt(paramStr[1]));
return true;
}
}
...@@ -630,6 +630,12 @@ public class Scene { ...@@ -630,6 +630,12 @@ public class Scene {
onLoadGroup(groups); onLoadGroup(groups);
Grasscutter.getLogger().info("Scene {} Block {} loaded.", this.getId(), block.id); Grasscutter.getLogger().info("Scene {} Block {} loaded.", this.getId(), block.id);
} }
public void loadTriggerFromGroup(SceneGroup group, String triggerName) {
//Load triggers and regions
getScriptManager().registerTrigger(group.triggers.values().stream().filter(p -> p.name.contains(triggerName)).toList());
group.regions.values().stream().filter(q -> q.config_id == Integer.parseInt(triggerName.substring(13))).map(region -> new EntityRegion(this, region))
.forEach(getScriptManager()::registerRegion);
}
public void onLoadGroup(List<SceneGroup> groups) { public void onLoadGroup(List<SceneGroup> groups) {
if (groups == null || groups.isEmpty()) { if (groups == null || groups.isEmpty()) {
......
...@@ -92,6 +92,7 @@ public class SceneScriptManager { ...@@ -92,6 +92,7 @@ public class SceneScriptManager {
} }
public void registerTrigger(SceneTrigger trigger) { public void registerTrigger(SceneTrigger trigger) {
getTriggersByEvent(trigger.event).add(trigger); getTriggersByEvent(trigger.event).add(trigger);
Grasscutter.getLogger().debug("Registered trigger {}", trigger.name);
} }
public void deregisterTrigger(List<SceneTrigger> triggers) { public void deregisterTrigger(List<SceneTrigger> triggers) {
triggers.forEach(this::deregisterTrigger); triggers.forEach(this::deregisterTrigger);
...@@ -122,6 +123,7 @@ public class SceneScriptManager { ...@@ -122,6 +123,7 @@ public class SceneScriptManager {
public void registerRegion(EntityRegion region) { public void registerRegion(EntityRegion region) {
regions.put(region.getId(), region); regions.put(region.getId(), region);
Grasscutter.getLogger().debug("Registered region {} from group {}", region.getMetaRegion().config_id, region.getGroupId());
} }
public void registerRegionInGroupSuite(SceneGroup group, SceneSuite suite){ public void registerRegionInGroupSuite(SceneGroup group, SceneSuite suite){
suite.sceneRegions.stream().map(region -> new EntityRegion(this.getScene(), region)) suite.sceneRegions.stream().map(region -> new EntityRegion(this.getScene(), region))
...@@ -195,9 +197,30 @@ public class SceneScriptManager { ...@@ -195,9 +197,30 @@ public class SceneScriptManager {
.filter(e -> e.getEntityType() == EntityType.Avatar.getValue() && region.getMetaRegion().contains(e.getPosition())) .filter(e -> e.getEntityType() == EntityType.Avatar.getValue() && region.getMetaRegion().contains(e.getPosition()))
.forEach(region::addEntity); .forEach(region::addEntity);
var players = region.getScene().getPlayers();
int targetID = 0;
if(players.size() > 0)
targetID = players.get(0).getUid();
if (region.hasNewEntities()) { if (region.hasNewEntities()) {
Grasscutter.getLogger().trace("Call EVENT_ENTER_REGION_{}",region.getMetaRegion().config_id);
callEvent(EventType.EVENT_ENTER_REGION, new ScriptArgs(region.getConfigId()) callEvent(EventType.EVENT_ENTER_REGION, new ScriptArgs(region.getConfigId())
.setSourceEntityId(region.getId()) .setSourceEntityId(region.getId())
.setTargetEntityId(targetID)
);
region.resetNewEntities();
}
for(int entityId : region.getEntities()) {
if(getScene().getEntityById(entityId) == null || !region.getMetaRegion().contains(getScene().getEntityById(entityId).getPosition())) {
region.removeEntity(entityId);
}
}
if (region.entityLeave()) {
callEvent(EventType.EVENT_LEAVE_REGION, new ScriptArgs(region.getConfigId())
.setSourceEntityId(region.getId())
.setTargetEntityId(region.getFirstEntityId()) .setTargetEntityId(region.getFirstEntityId())
); );
...@@ -286,22 +309,36 @@ public class SceneScriptManager { ...@@ -286,22 +309,36 @@ public class SceneScriptManager {
} }
private void realCallEvent(int eventType, ScriptArgs params) { private void realCallEvent(int eventType, ScriptArgs params) {
try{ try {
ScriptLoader.getScriptLib().setSceneScriptManager(this); Set<SceneTrigger> relevantTriggers = new HashSet<>();
for (SceneTrigger trigger : this.getTriggersByEvent(eventType)) { if(eventType == EventType.EVENT_ENTER_REGION || eventType == EventType.EVENT_LEAVE_REGION) {
try{ List<SceneTrigger> relevantTriggersList = this.getTriggersByEvent(eventType).stream()
.filter(p -> p.condition.contains(String.valueOf(params.param1))).toList();
relevantTriggers = new HashSet<>(relevantTriggersList);
} else {relevantTriggers = this.getTriggersByEvent(eventType);}
for (SceneTrigger trigger : relevantTriggers) {
try {
ScriptLoader.getScriptLib().setCurrentGroup(trigger.currentGroup); ScriptLoader.getScriptLib().setCurrentGroup(trigger.currentGroup);
LuaValue ret = this.callScriptFunc(trigger.condition, trigger.currentGroup, params);
LuaValue ret = callScriptFunc(trigger.condition, trigger.currentGroup, params); Grasscutter.getLogger().trace("Call Condition Trigger {}, [{},{},{}]", trigger.condition, params.param1, params.source_eid, params.target_eid);
Grasscutter.getLogger().trace("Call Condition Trigger {}", trigger.condition);
if (ret.isboolean() && ret.checkboolean()) { if (ret.isboolean() && ret.checkboolean()) {
// the SetGroupVariableValueByGroup in tower need the param to record the first stage time // the SetGroupVariableValueByGroup in tower need the param to record the first stage time
callScriptFunc(trigger.action, trigger.currentGroup, params); this.callScriptFunc(trigger.action, trigger.currentGroup, params);
Grasscutter.getLogger().trace("Call Action Trigger {}", trigger.action); Grasscutter.getLogger().trace("Call Action Trigger {}", trigger.action);
} if (trigger.event == EventType.EVENT_ENTER_REGION) {
//TODO some ret may not bool EntityRegion region = this.regions.values().stream().filter(p -> p.getConfigId() == params.param1).toList().get(0);
getScene().getPlayers().forEach(p -> p.onEnterRegion(region.getMetaRegion()));
deregisterRegion(region.getMetaRegion());
} else if (trigger.event == EventType.EVENT_LEAVE_REGION) {
EntityRegion region = this.regions.values().stream().filter(p -> p.getConfigId() == params.param1).toList().get(0);
getScene().getPlayers().forEach(p -> p.onLeaveRegion(region.getMetaRegion()));
deregisterRegion(region.getMetaRegion());
}
deregisterTrigger(trigger);
} else {
Grasscutter.getLogger().debug("Condition Trigger {} returned {}", trigger.condition, ret);
}
//TODO some ret do not bool
}finally { }finally {
ScriptLoader.getScriptLib().removeCurrentGroup(); ScriptLoader.getScriptLib().removeCurrentGroup();
} }
......
...@@ -12,6 +12,7 @@ public class SceneGadget extends SceneObject{ ...@@ -12,6 +12,7 @@ public class SceneGadget extends SceneObject{
public SceneBossChest boss_chest; public SceneBossChest boss_chest;
public int interact_id; public int interact_id;
public boolean isOneoff; public boolean isOneoff;
public int draft_id;
public void setIsOneoff(boolean isOneoff){ public void setIsOneoff(boolean isOneoff){
this.isOneoff = isOneoff; this.isOneoff = isOneoff;
......
...@@ -26,7 +26,8 @@ public class SceneRegion { ...@@ -26,7 +26,8 @@ public class SceneRegion {
var x = Math.pow(pos.getX() - position.getX(), 2); var x = Math.pow(pos.getX() - position.getX(), 2);
var y = Math.pow(pos.getY() - position.getY(), 2); var y = Math.pow(pos.getY() - position.getY(), 2);
var z = Math.pow(pos.getZ() - position.getZ(), 2); var z = Math.pow(pos.getZ() - position.getZ(), 2);
return x + y + z <= (radius ^ 2); // ^ means XOR in java!
return x + y + z <= (radius*radius);
} }
return false; return false;
} }
......
...@@ -30,6 +30,54 @@ public class LuaSerializer implements Serializer { ...@@ -30,6 +30,54 @@ public class LuaSerializer implements Serializer {
return serialize(type, (LuaTable) obj); return serialize(type, (LuaTable) obj);
} }
@Override
public <T> Map<String, T> toMap(Class<T> type, Object obj) {
return serializeMap(type, (LuaTable) obj);
}
private <T> Map<String,T> serializeMap(Class<T> type, LuaTable table) {
Map<String,T> map = new HashMap<>();
if (table == null) {
return map;
}
try {
LuaValue[] keys = table.keys();
for (LuaValue k : keys) {
try {
LuaValue keyValue = table.get(k);
T object = null;
if (keyValue.istable()) {
object = serialize(type, keyValue.checktable());
} else if (keyValue.isint()) {
object = (T) (Integer) keyValue.toint();
} else if (keyValue.isnumber()) {
object = (T) (Float) keyValue.tofloat(); // terrible...
} else if (keyValue.isstring()) {
object = (T) keyValue.tojstring();
} else if (keyValue.isboolean()) {
object = (T) (Boolean) keyValue.toboolean();
} else {
object = (T) keyValue;
}
if (object != null) {
map.put(String.valueOf(k),object);
}
} catch (Exception ex) {
}
}
} catch (Exception e) {
e.printStackTrace();
}
return map;
}
public <T> List<T> serializeList(Class<T> type, LuaTable table) { public <T> List<T> serializeList(Class<T> type, LuaTable table) {
List<T> list = new ArrayList<>(); List<T> list = new ArrayList<>();
......
package emu.grasscutter.scripts.serializer; package emu.grasscutter.scripts.serializer;
import java.util.List; import java.util.List;
import java.util.Map;
import org.luaj.vm2.LuaTable;
public interface Serializer { public interface Serializer {
public <T> List<T> toList(Class<T> type, Object obj); public <T> List<T> toList(Class<T> type, Object obj);
public <T> T toObject(Class<T> type, Object obj); public <T> T toObject(Class<T> type, Object obj);
public <T> Map<String,T> toMap(Class<T> type, Object obj);
} }
package emu.grasscutter.server.packet.recv; package emu.grasscutter.server.packet.recv;
import emu.grasscutter.data.GameData;
import emu.grasscutter.data.excels.QuestData;
import emu.grasscutter.game.quest.GameQuest;
import emu.grasscutter.game.quest.enums.QuestTrigger; import emu.grasscutter.game.quest.enums.QuestTrigger;
import emu.grasscutter.net.packet.Opcodes; import emu.grasscutter.net.packet.Opcodes;
import emu.grasscutter.net.packet.PacketHandler; import emu.grasscutter.net.packet.PacketHandler;
...@@ -7,6 +10,9 @@ import emu.grasscutter.net.packet.PacketOpcodes; ...@@ -7,6 +10,9 @@ import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.proto.AddQuestContentProgressReqOuterClass; import emu.grasscutter.net.proto.AddQuestContentProgressReqOuterClass;
import emu.grasscutter.server.game.GameSession; import emu.grasscutter.server.game.GameSession;
import emu.grasscutter.server.packet.send.PacketAddQuestContentProgressRsp; import emu.grasscutter.server.packet.send.PacketAddQuestContentProgressRsp;
import emu.grasscutter.data.excels.QuestData.QuestCondition;
import java.util.List;
import java.util.stream.Stream;
@Opcodes(PacketOpcodes.AddQuestContentProgressReq) @Opcodes(PacketOpcodes.AddQuestContentProgressReq)
public class HandlerAddQuestContentProgressReq extends PacketHandler { public class HandlerAddQuestContentProgressReq extends PacketHandler {
...@@ -14,9 +20,14 @@ public class HandlerAddQuestContentProgressReq extends PacketHandler { ...@@ -14,9 +20,14 @@ public class HandlerAddQuestContentProgressReq extends PacketHandler {
@Override @Override
public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { public void handle(GameSession session, byte[] header, byte[] payload) throws Exception {
var req = AddQuestContentProgressReqOuterClass.AddQuestContentProgressReq.parseFrom(payload); var req = AddQuestContentProgressReqOuterClass.AddQuestContentProgressReq.parseFrom(payload);
//Find all conditions in quest that are the same as the given one
session.getPlayer().getQuestManager().triggerEvent(QuestTrigger.getContentTriggerByValue(req.getContentType()), req.getParam()); Stream<QuestCondition> finishCond = GameData.getQuestDataMap().get(req.getParam()).getFinishCond().stream();
Stream<QuestCondition> acceptCond = GameData.getQuestDataMap().get(req.getParam()).getAcceptCond().stream();
Stream<QuestCondition> failCond = GameData.getQuestDataMap().get(req.getParam()).getFailCond().stream();
List<QuestCondition> allCondMatch = Stream.concat(Stream.concat(acceptCond,failCond),finishCond).filter(p -> p.getType().getValue() == req.getContentType()).toList();
for(QuestCondition cond : allCondMatch ) {
session.getPlayer().getQuestManager().triggerEvent(QuestTrigger.getContentTriggerByValue(req.getContentType()), cond.getParam());
}
session.send(new PacketAddQuestContentProgressRsp(req.getContentType())); session.send(new PacketAddQuestContentProgressRsp(req.getContentType()));
} }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment