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,10 +5,17 @@ public enum QuestState {
QUEST_STATE_UNSTARTED (1),
QUEST_STATE_UNFINISHED (2),
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;
QuestState(int id) {
this.value = id;
}
......
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;
}
}
......@@ -627,8 +627,14 @@ public class Scene {
.flatMap(Collection::stream)
.toList();
onLoadGroup(groups);
Grasscutter.getLogger().info("Scene {} Block {} loaded.", this.getId(), block.id);
onLoadGroup(groups);
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) {
......
......@@ -92,6 +92,7 @@ public class SceneScriptManager {
}
public void registerTrigger(SceneTrigger trigger) {
getTriggersByEvent(trigger.event).add(trigger);
Grasscutter.getLogger().debug("Registered trigger {}", trigger.name);
}
public void deregisterTrigger(List<SceneTrigger> triggers) {
triggers.forEach(this::deregisterTrigger);
......@@ -122,6 +123,7 @@ public class SceneScriptManager {
public void registerRegion(EntityRegion 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){
suite.sceneRegions.stream().map(region -> new EntityRegion(this.getScene(), region))
......@@ -195,9 +197,30 @@ public class SceneScriptManager {
.filter(e -> e.getEntityType() == EntityType.Avatar.getValue() && region.getMetaRegion().contains(e.getPosition()))
.forEach(region::addEntity);
var players = region.getScene().getPlayers();
int targetID = 0;
if(players.size() > 0)
targetID = players.get(0).getUid();
if (region.hasNewEntities()) {
Grasscutter.getLogger().trace("Call EVENT_ENTER_REGION_{}",region.getMetaRegion().config_id);
callEvent(EventType.EVENT_ENTER_REGION, new ScriptArgs(region.getConfigId())
.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())
);
......@@ -286,27 +309,41 @@ public class SceneScriptManager {
}
private void realCallEvent(int eventType, ScriptArgs params) {
try{
ScriptLoader.getScriptLib().setSceneScriptManager(this);
for (SceneTrigger trigger : this.getTriggersByEvent(eventType)) {
try{
ScriptLoader.getScriptLib().setCurrentGroup(trigger.currentGroup);
LuaValue ret = callScriptFunc(trigger.condition, trigger.currentGroup, params);
Grasscutter.getLogger().trace("Call Condition Trigger {}", trigger.condition);
if (ret.isboolean() && ret.checkboolean()) {
// the SetGroupVariableValueByGroup in tower need the param to record the first stage time
callScriptFunc(trigger.action, trigger.currentGroup, params);
Grasscutter.getLogger().trace("Call Action Trigger {}", trigger.action);
}
//TODO some ret may not bool
}finally {
ScriptLoader.getScriptLib().removeCurrentGroup();
}
}
}finally {
try {
Set<SceneTrigger> relevantTriggers = new HashSet<>();
if(eventType == EventType.EVENT_ENTER_REGION || eventType == EventType.EVENT_LEAVE_REGION) {
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);
LuaValue ret = this.callScriptFunc(trigger.condition, trigger.currentGroup, params);
Grasscutter.getLogger().trace("Call Condition Trigger {}, [{},{},{}]", trigger.condition, params.param1, params.source_eid, params.target_eid);
if (ret.isboolean() && ret.checkboolean()) {
// the SetGroupVariableValueByGroup in tower need the param to record the first stage time
this.callScriptFunc(trigger.action, trigger.currentGroup, params);
Grasscutter.getLogger().trace("Call Action Trigger {}", trigger.action);
if (trigger.event == EventType.EVENT_ENTER_REGION) {
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 {
ScriptLoader.getScriptLib().removeCurrentGroup();
}
}
}finally {
// make sure it is removed
ScriptLoader.getScriptLib().removeSceneScriptManager();
}
......
......@@ -12,6 +12,7 @@ public class SceneGadget extends SceneObject{
public SceneBossChest boss_chest;
public int interact_id;
public boolean isOneoff;
public int draft_id;
public void setIsOneoff(boolean isOneoff){
this.isOneoff = isOneoff;
......
......@@ -26,7 +26,8 @@ public class SceneRegion {
var x = Math.pow(pos.getX() - position.getX(), 2);
var y = Math.pow(pos.getY() - position.getY(), 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;
}
......
......@@ -29,22 +29,70 @@ public class LuaSerializer implements Serializer {
public <T> T toObject(Class<T> type, Object obj) {
return serialize(type, (LuaTable) obj);
}
public <T> List<T> serializeList(Class<T> type, LuaTable table) {
@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) {
List<T> list = new ArrayList<>();
if (table == null) {
return list;
}
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()) {
......@@ -75,7 +123,7 @@ public class LuaSerializer implements Serializer {
public <T> T serialize(Class<T> type, LuaTable table) {
T object = null;
if (type == List.class) {
try {
Class<T> listType = (Class<T>) type.getTypeParameters()[0].getClass();
......@@ -85,7 +133,7 @@ public class LuaSerializer implements Serializer {
return null;
}
}
try {
if (!methodAccessCache.containsKey(type)) {
cacheType(type);
......@@ -98,7 +146,7 @@ public class LuaSerializer implements Serializer {
if (table == null) {
return object;
}
LuaValue[] keys = table.keys();
for (LuaValue k : keys) {
try {
......@@ -131,7 +179,7 @@ public class LuaSerializer implements Serializer {
Grasscutter.getLogger().info(ScriptUtils.toMap(table).toString());
e.printStackTrace();
}
return object;
}
......
package emu.grasscutter.scripts.serializer;
import java.util.List;
import java.util.Map;
import org.luaj.vm2.LuaTable;
public interface Serializer {
public <T> List<T> toList(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;
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.net.packet.Opcodes;
import emu.grasscutter.net.packet.PacketHandler;
......@@ -7,6 +10,9 @@ import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.proto.AddQuestContentProgressReqOuterClass;
import emu.grasscutter.server.game.GameSession;
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)
public class HandlerAddQuestContentProgressReq extends PacketHandler {
......@@ -14,9 +20,14 @@ public class HandlerAddQuestContentProgressReq extends PacketHandler {
@Override
public void handle(GameSession session, byte[] header, byte[] payload) throws Exception {
var req = AddQuestContentProgressReqOuterClass.AddQuestContentProgressReq.parseFrom(payload);
session.getPlayer().getQuestManager().triggerEvent(QuestTrigger.getContentTriggerByValue(req.getContentType()), req.getParam());
//Find all conditions in quest that are the same as the given one
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()));
}
......
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