Enable script in big world (#884)

* add docs for tower

* fix: LEAK: ByteBuf.release() was not called

* enableScriptInBigWorld

* not print log when loaded scripts from cache

* revert the change of server tick

* revert the change of server tick

* fix

* optimize the performance: lazy load & cache

* fix the refresh group

* fix NPE

Co-authored-by: Melledy <52122272+Melledy@users.noreply.github.com>
This commit is contained in:
Akka
2022-05-15 19:19:24 +08:00
committed by GitHub
parent eb64b25f12
commit 6dc30e4def
21 changed files with 643 additions and 321 deletions

View File

@@ -0,0 +1,71 @@
package emu.grasscutter.scripts.data;
import ch.ethz.globis.phtree.PhTree;
import ch.ethz.globis.phtree.v16.PhTree16;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.scripts.SceneIndexManager;
import emu.grasscutter.scripts.ScriptLoader;
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;
import static emu.grasscutter.Configuration.SCRIPT;
public class SceneMeta {
public SceneConfig config;
public Map<Integer, SceneBlock> blocks;
public Bindings context;
public PhTree<SceneBlock> sceneBlockIndex = new PhTree16<>(2);
public static SceneMeta of(int sceneId) {
return new SceneMeta().load(sceneId);
}
public SceneMeta load(int sceneId){
// Get compiled script if cached
CompiledScript cs = ScriptLoader.getScriptByPath(
SCRIPT("Scene/" + sceneId + "/scene" + sceneId + "." + ScriptLoader.getScriptType()));
if (cs == null) {
Grasscutter.getLogger().warn("No script found for scene " + sceneId);
return null;
}
// Create bindings
context = ScriptLoader.getEngine().createBindings();
// Eval script
try {
cs.eval(context);
this.config = ScriptLoader.getSerializer().toObject(SceneConfig.class, context.get("scene_config"));
// TODO optimize later
// Create blocks
List<Integer> blockIds = ScriptLoader.getSerializer().toList(Integer.class, context.get("blocks"));
List<SceneBlock> blocks = ScriptLoader.getSerializer().toList(SceneBlock.class, context.get("block_rects"));
for (int i = 0; i < blocks.size(); i++) {
SceneBlock block = blocks.get(i);
block.id = blockIds.get(i);
}
this.blocks = blocks.stream().collect(Collectors.toMap(b -> b.id, b -> b));
SceneIndexManager.buildIndex(this.sceneBlockIndex, blocks, g -> g.min.toXZLongArray());
SceneIndexManager.buildIndex(this.sceneBlockIndex, blocks, g -> g.max.toXZLongArray());
} catch (ScriptException e) {
Grasscutter.getLogger().error("Error running script", e);
return null;
}
Grasscutter.getLogger().info("scene {} metadata is loaded successfully.", sceneId);
return this;
}
}