Copy some files from Grasscutter-Quests

NOT completely finished, nor is it completely done. Protocol issues remain! (including lack of packet IDs)
This commit is contained in:
KingRainbow44
2023-04-01 18:06:30 -04:00
parent 262ee38ded
commit daa51e53b7
381 changed files with 10285 additions and 9150 deletions

View File

@@ -1,53 +1,54 @@
package emu.grasscutter.scripts;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.scripts.data.controller.EntityController;
import lombok.val;
import javax.script.Bindings;
import javax.script.CompiledScript;
import java.io.IOException;
import java.nio.file.Files;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import static emu.grasscutter.utils.FileUtils.getScriptPath;
public class EntityControllerScriptManager {
private static final Map<String, EntityController> gadgetController = new ConcurrentHashMap<>();
public static void load(){
cacheGadgetControllers();
}
private static void cacheGadgetControllers(){
try {
Files.newDirectoryStream(getScriptPath("Gadget/"), "*.lua").forEach(path -> {
val fileName = path.getFileName().toString();
if(!fileName.endsWith(".lua")) return;
val controllerName = fileName.substring(0, fileName.length()-4);
CompiledScript cs = ScriptLoader.getScript("Gadget/"+fileName);
Bindings bindings = ScriptLoader.getEngine().createBindings();
if (cs == null) return;
try{
cs.eval(bindings);
gadgetController.put(controllerName, new EntityController(cs, bindings));
} catch (Throwable e){
Grasscutter.getLogger().error("Error while loading gadget controller: {}", fileName);
}
});
Grasscutter.getLogger().info("Loaded {} gadget controllers", gadgetController.size());
} catch (IOException e) {
Grasscutter.getLogger().error("Error loading gadget controller luas");
}
}
public static EntityController getGadgetController(String name) {
return gadgetController.get(name);
}
}
package emu.grasscutter.scripts;
import static emu.grasscutter.utils.FileUtils.getScriptPath;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.scripts.data.controller.EntityController;
import java.io.IOException;
import java.nio.file.Files;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.script.Bindings;
import javax.script.CompiledScript;
import lombok.val;
public class EntityControllerScriptManager {
private static final Map<String, EntityController> gadgetController = new ConcurrentHashMap<>();
public static void load() {
cacheGadgetControllers();
}
private static void cacheGadgetControllers() {
try {
Files.newDirectoryStream(getScriptPath("Gadget/"), "*.lua")
.forEach(
path -> {
val fileName = path.getFileName().toString();
if (!fileName.endsWith(".lua")) return;
val controllerName = fileName.substring(0, fileName.length() - 4);
CompiledScript cs = ScriptLoader.getScript("Gadget/" + fileName);
Bindings bindings = ScriptLoader.getEngine().createBindings();
if (cs == null) return;
try {
cs.eval(bindings);
gadgetController.put(controllerName, new EntityController(cs, bindings));
} catch (Throwable e) {
Grasscutter.getLogger()
.error("Error while loading gadget controller: {}", fileName);
}
});
Grasscutter.getLogger().info("Loaded {} gadget controllers", gadgetController.size());
} catch (IOException e) {
Grasscutter.getLogger().error("Error loading gadget controller luas");
}
}
public static EntityController getGadgetController(String name) {
return gadgetController.get(name);
}
}

View File

@@ -4,8 +4,8 @@ import com.github.davidmoten.rtreemulti.RTree;
import com.github.davidmoten.rtreemulti.geometry.Geometry;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.GameData;
import emu.grasscutter.data.excels.MonsterData;
import emu.grasscutter.data.excels.WorldLevelData;
import emu.grasscutter.data.excels.monster.MonsterData;
import emu.grasscutter.data.excels.world.WorldLevelData;
import emu.grasscutter.game.entity.*;
import emu.grasscutter.game.props.EntityType;
import emu.grasscutter.game.world.Scene;

View File

@@ -518,7 +518,7 @@ public class ScriptLib {
for (var player : getSceneScriptManager().getScene().getPlayers()) {
player.getQuestManager().triggerEvent(QuestTrigger.QUEST_COND_LUA_NOTIFY, var1);
player.getQuestManager().triggerEvent(QuestTrigger.QUEST_CONTENT_LUA_NOTIFY, var1);
player.getQuestManager().triggerEvent(QuestContent.QUEST_CONTENT_LUA_NOTIFY, var1);
}
return 0;

View File

@@ -1,9 +1,9 @@
package emu.grasscutter.scripts.constants;
public enum GroupKillPolicy {
GROUP_KILL_NONE,
GROUP_KILL_ALL,
GROUP_KILL_MONSTER,
GROUP_KILL_GADGET,
GROUP_KILL_NPC
}
package emu.grasscutter.scripts.constants;
public enum GroupKillPolicy {
GROUP_KILL_NONE,
GROUP_KILL_ALL,
GROUP_KILL_MONSTER,
GROUP_KILL_GADGET,
GROUP_KILL_NPC
}

View File

@@ -1,5 +1,5 @@
package emu.grasscutter.scripts.constants;
public interface IntValueEnum {
int getValue();
}
package emu.grasscutter.scripts.constants;
public interface IntValueEnum {
int getValue();
}

View File

@@ -1,7 +1,7 @@
package emu.grasscutter.scripts.constants;
public enum SealBattleType {
NONE,
ENERGY_CHARGE,
KILL_MONSTER
}
package emu.grasscutter.scripts.constants;
public enum SealBattleType {
NONE,
ENERGY_CHARGE,
KILL_MONSTER
}

View File

@@ -13,13 +13,10 @@ public class SceneGadget extends SceneObject {
public int interact_id;
public boolean isOneoff;
public int draft_id;
public String drop_tag;
public boolean persistent;
public int mark_flag;
public int route_id;
public Explore explore;
public int trigger_count;
public boolean showcutscene;
public boolean start_route = true;
public boolean is_use_point_array = false;
public boolean persistent = false;
public void setIsOneoff(boolean isOneoff) {
this.isOneoff = isOneoff;

View File

@@ -1,12 +1,12 @@
package emu.grasscutter.scripts.data;
import lombok.Setter;
import lombok.ToString;
@ToString
@Setter
public class SceneReplaceable {
public boolean value;
public int version;
public boolean new_bin_only;
}
package emu.grasscutter.scripts.data;
import lombok.Setter;
import lombok.ToString;
@ToString
@Setter
public class SceneReplaceable {
public boolean value;
public int version;
public boolean new_bin_only;
}

View File

@@ -1,67 +1,104 @@
package emu.grasscutter.scripts.data.controller;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.game.entity.GameEntity;
import emu.grasscutter.game.props.ElementType;
import emu.grasscutter.scripts.ScriptLib;
import emu.grasscutter.scripts.ScriptLoader;
import org.luaj.vm2.LuaError;
import org.luaj.vm2.LuaValue;
import javax.script.Bindings;
import javax.script.CompiledScript;
public class EntityController {
private transient CompiledScript entityController;
private transient Bindings entityControllerBindings;
public EntityController(CompiledScript entityController, Bindings entityControllerBindings){
this.entityController = entityController;
this.entityControllerBindings = entityControllerBindings;
}
public void onBeHurt(GameEntity entity, ElementType elementType, boolean isHost) {
callControllerScriptFunc(entity, "OnBeHurt", LuaValue.valueOf(elementType.getValue()), LuaValue.valueOf(0), LuaValue.valueOf(isHost));
}
public void onDie(GameEntity entity, ElementType elementType) {
callControllerScriptFunc(entity, "OnDie", LuaValue.valueOf(elementType.getValue()), LuaValue.valueOf(0));
}
public void onTimer(GameEntity entity, int now) {
callControllerScriptFunc(entity, "OnTimer", LuaValue.valueOf(now));
}
public int onClientExecuteRequest(GameEntity entity, int param1, int param2, int param3) {
Grasscutter.getLogger().debug("Request on {}, {}: {}", entity.getGroupId(), param1, entity.getPosition().toString());
LuaValue value = callControllerScriptFunc(entity, "OnClientExecuteReq", LuaValue.valueOf(param1), LuaValue.valueOf(param2), LuaValue.valueOf(param3));
if(value.isint() && value.toint() == 1) return 1;
return 0;
}
// TODO actual execution should probably be handle by EntityControllerScriptManager
private LuaValue callControllerScriptFunc(GameEntity entity, String funcName, LuaValue arg1) { return callControllerScriptFunc(entity, funcName, arg1, LuaValue.NIL, LuaValue.NIL); }
private LuaValue callControllerScriptFunc(GameEntity entity, String funcName, LuaValue arg1, LuaValue arg2) { return callControllerScriptFunc(entity, funcName, arg1, arg2, LuaValue.NIL); }
private LuaValue callControllerScriptFunc(GameEntity entity, String funcName, LuaValue arg1, LuaValue arg2, LuaValue arg3) {
LuaValue funcLua = null;
if (funcName != null && !funcName.isEmpty()) {
funcLua = (LuaValue) entityControllerBindings.get(funcName);
}
LuaValue ret = LuaValue.ONE;
if (funcLua != null) {
try {
ScriptLoader.getScriptLib().setCurrentEntity(entity);
ret = funcLua.invoke(new LuaValue[]{ScriptLoader.getScriptLibLua(), arg1, arg2, arg3}).arg1();
}catch (LuaError error) {
ScriptLib.logger.error("[LUA] call function failed in gadget {} with {} {} {},{}", entity.getEntityTypeId(), funcName, arg1, arg2, arg3, error);
ret = LuaValue.valueOf(-1);
}
} else if(funcName != null && !funcName.equals("OnTimer")) {
ScriptLib.logger.error("[LUA] unknown func in gadget {} with {} {} {} {}", entity.getEntityTypeId(), funcName, arg1, arg2, arg3);
}
return ret;
}
}
package emu.grasscutter.scripts.data.controller;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.game.entity.GameEntity;
import emu.grasscutter.game.props.ElementType;
import emu.grasscutter.scripts.ScriptLib;
import emu.grasscutter.scripts.ScriptLoader;
import javax.script.Bindings;
import javax.script.CompiledScript;
import org.luaj.vm2.LuaError;
import org.luaj.vm2.LuaValue;
public class EntityController {
private transient CompiledScript entityController;
private transient Bindings entityControllerBindings;
public EntityController(CompiledScript entityController, Bindings entityControllerBindings) {
this.entityController = entityController;
this.entityControllerBindings = entityControllerBindings;
}
public void onBeHurt(GameEntity entity, ElementType elementType, boolean isHost) {
callControllerScriptFunc(
entity,
"OnBeHurt",
LuaValue.valueOf(elementType.getValue()),
LuaValue.valueOf(0),
LuaValue.valueOf(isHost));
}
public void onDie(GameEntity entity, ElementType elementType) {
callControllerScriptFunc(
entity, "OnDie", LuaValue.valueOf(elementType.getValue()), LuaValue.valueOf(0));
}
public void onTimer(GameEntity entity, int now) {
callControllerScriptFunc(entity, "OnTimer", LuaValue.valueOf(now));
}
public int onClientExecuteRequest(GameEntity entity, int param1, int param2, int param3) {
Grasscutter.getLogger()
.debug(
"Request on {}, {}: {}", entity.getGroupId(), param1, entity.getPosition().toString());
LuaValue value =
callControllerScriptFunc(
entity,
"OnClientExecuteReq",
LuaValue.valueOf(param1),
LuaValue.valueOf(param2),
LuaValue.valueOf(param3));
if (value.isint() && value.toint() == 1) return 1;
return 0;
}
// TODO actual execution should probably be handle by EntityControllerScriptManager
private LuaValue callControllerScriptFunc(GameEntity entity, String funcName, LuaValue arg1) {
return callControllerScriptFunc(entity, funcName, arg1, LuaValue.NIL, LuaValue.NIL);
}
private LuaValue callControllerScriptFunc(
GameEntity entity, String funcName, LuaValue arg1, LuaValue arg2) {
return callControllerScriptFunc(entity, funcName, arg1, arg2, LuaValue.NIL);
}
private LuaValue callControllerScriptFunc(
GameEntity entity, String funcName, LuaValue arg1, LuaValue arg2, LuaValue arg3) {
LuaValue funcLua = null;
if (funcName != null && !funcName.isEmpty()) {
funcLua = (LuaValue) entityControllerBindings.get(funcName);
}
LuaValue ret = LuaValue.ONE;
if (funcLua != null) {
try {
ScriptLoader.getScriptLib().setCurrentEntity(entity);
ret =
funcLua
.invoke(new LuaValue[] {ScriptLoader.getScriptLibLua(), arg1, arg2, arg3})
.arg1();
} catch (LuaError error) {
ScriptLib.logger.error(
"[LUA] call function failed in gadget {} with {} {} {},{}",
entity.getEntityTypeId(),
funcName,
arg1,
arg2,
arg3,
error);
ret = LuaValue.valueOf(-1);
}
} else if (funcName != null && !funcName.equals("OnTimer")) {
ScriptLib.logger.error(
"[LUA] unknown func in gadget {} with {} {} {} {}",
entity.getEntityTypeId(),
funcName,
arg1,
arg2,
arg3);
}
return ret;
}
}