Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
ziqian zhang
Grasscutter
Commits
bad85357
Commit
bad85357
authored
May 19, 2022
by
Akka
Committed by
Melledy
May 18, 2022
Browse files
optimized the Lua func binding so that the script will not eval again
parent
a8f38ad9
Changes
7
Hide whitespace changes
Inline
Side-by-side
src/main/java/emu/grasscutter/game/dungeons/DungeonChallenge.java
View file @
bad85357
...
...
@@ -138,7 +138,9 @@ public class DungeonChallenge {
getScene
().
getDungeonSettleObservers
().
forEach
(
o
->
o
.
onDungeonSettle
(
getScene
()));
if
(!
stage
){
getScene
().
getScriptManager
().
callEvent
(
EventType
.
EVENT_DUNGEON_SETTLE
,
new
ScriptArgs
(
this
.
isSuccess
()
?
1
:
0
));
getScene
().
getScriptManager
().
callEvent
(
EventType
.
EVENT_DUNGEON_SETTLE
,
// TODO record the time in PARAM2 and used in action
new
ScriptArgs
(
this
.
isSuccess
()
?
1
:
0
,
100
));
}
}
...
...
src/main/java/emu/grasscutter/game/world/WorldDataManager.java
View file @
bad85357
...
...
@@ -26,7 +26,7 @@ public class WorldDataManager {
}
public
synchronized
void
load
(){
try
(
InputStream
is
=
DataLoader
.
load
(
"ChestReward.json"
,
false
);
InputStreamReader
isr
=
new
InputStreamReader
(
is
))
{
try
(
InputStream
is
=
DataLoader
.
load
(
"ChestReward.json"
);
InputStreamReader
isr
=
new
InputStreamReader
(
is
))
{
List
<
ChestReward
>
chestReward
=
Grasscutter
.
getGsonFactory
().
fromJson
(
isr
,
TypeToken
.
getParameterized
(
List
.
class
,
ChestReward
.
class
).
getType
());
...
...
src/main/java/emu/grasscutter/scripts/SceneScriptManager.java
View file @
bad85357
...
...
@@ -20,16 +20,11 @@ import org.luaj.vm2.LuaError;
import
org.luaj.vm2.LuaValue
;
import
org.luaj.vm2.lib.jse.CoerceJavaToLua
;
import
javax.script.Bindings
;
import
javax.script.ScriptException
;
import
java.util.*
;
public
class
SceneScriptManager
{
private
final
Scene
scene
;
private
final
ScriptLib
scriptLib
;
private
final
LuaValue
scriptLibLua
;
private
final
Map
<
String
,
Integer
>
variables
;
private
Bindings
bindings
;
private
SceneMeta
meta
;
private
boolean
isInit
;
/**
...
...
@@ -50,8 +45,6 @@ public class SceneScriptManager {
private
Int2ObjectMap
<
Set
<
SceneGroup
>>
loadedGroupSetPerBlock
;
public
SceneScriptManager
(
Scene
scene
)
{
this
.
scene
=
scene
;
this
.
scriptLib
=
new
ScriptLib
(
this
);
this
.
scriptLibLua
=
CoerceJavaToLua
.
coerce
(
this
.
scriptLib
);
this
.
triggers
=
new
HashMap
<>();
this
.
currentTriggers
=
new
Int2ObjectOpenHashMap
<>();
...
...
@@ -74,18 +67,6 @@ public class SceneScriptManager {
return
scene
;
}
public
ScriptLib
getScriptLib
()
{
return
scriptLib
;
}
public
LuaValue
getScriptLibLua
()
{
return
scriptLibLua
;
}
public
Bindings
getBindings
()
{
return
bindings
;
}
public
SceneConfig
getConfig
()
{
if
(!
isInit
){
return
null
;
...
...
@@ -162,11 +143,6 @@ public class SceneScriptManager {
}
private
void
init
()
{
// Create bindings
bindings
=
ScriptLoader
.
getEngine
().
createBindings
();
// Set variables
bindings
.
put
(
"ScriptLib"
,
getScriptLib
());
var
meta
=
ScriptLoader
.
getSceneMeta
(
getScene
().
getId
());
if
(
meta
==
null
){
return
;
...
...
@@ -186,14 +162,7 @@ public class SceneScriptManager {
}
public
void
loadGroupFromScript
(
SceneGroup
group
)
{
group
.
load
(
getScene
().
getId
(),
meta
.
context
);
try
{
// build the trigger for this scene
group
.
getScript
().
eval
(
getBindings
());
}
catch
(
ScriptException
e
)
{
Grasscutter
.
getLogger
().
error
(
"Could not build the trigger for this scene"
,
e
);
}
group
.
load
(
getScene
().
getId
());
group
.
variables
.
forEach
(
var
->
this
.
getVariables
().
put
(
var
.
name
,
var
.
value
));
this
.
sceneGroups
.
put
(
group
.
id
,
group
);
...
...
@@ -284,47 +253,55 @@ public class SceneScriptManager {
// Events
public
void
callEvent
(
int
eventType
,
ScriptArgs
params
)
{
for
(
SceneTrigger
trigger
:
this
.
getTriggersByEvent
(
eventType
))
{
scriptLib
.
setCurrentGroup
(
trigger
.
currentGroup
);
LuaValue
condition
=
null
;
if
(
trigger
.
condition
!=
null
&&
!
trigger
.
condition
.
isEmpty
())
{
condition
=
(
LuaValue
)
this
.
getBindings
().
get
(
trigger
.
condition
);
}
LuaValue
ret
=
LuaValue
.
TRUE
;
if
(
condition
!=
null
)
{
LuaValue
args
=
LuaValue
.
NIL
;
if
(
params
!=
null
)
{
args
=
CoerceJavaToLua
.
coerce
(
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
ScriptLib
.
logger
.
trace
(
"Call Condition Trigger {}"
,
trigger
);
ret
=
safetyCall
(
trigger
.
condition
,
condition
,
args
);
}
if
(
ret
.
isboolean
()
&&
ret
.
checkboolean
())
{
if
(
trigger
.
action
==
null
||
trigger
.
action
.
isEmpty
()){
return
;
}
finally
{
ScriptLoader
.
getScriptLib
().
removeCurrentGroup
();
}
ScriptLib
.
logger
.
trace
(
"Call Action Trigger {}"
,
trigger
);
LuaValue
action
=
(
LuaValue
)
this
.
getBindings
().
get
(
trigger
.
action
);
// TODO impl the param of SetGroupVariableValueByGroup
var
arg
=
new
ScriptArgs
();
arg
.
param2
=
100
;
var
args
=
CoerceJavaToLua
.
coerce
(
arg
);
safetyCall
(
trigger
.
action
,
action
,
args
);
}
//TODO some ret may not bool
scriptLib
.
removeCurrentGroup
();
}
finally
{
// make sure it is removed
ScriptLoader
.
getScriptLib
().
removeSceneScriptManager
();
}
}
public
LuaValue
callScriptFunc
(
String
funcName
,
SceneGroup
group
,
ScriptArgs
params
){
LuaValue
funcLua
=
null
;
if
(
funcName
!=
null
&&
!
funcName
.
isEmpty
())
{
funcLua
=
(
LuaValue
)
group
.
getBindings
().
get
(
funcName
);
}
LuaValue
ret
=
LuaValue
.
TRUE
;
if
(
funcLua
!=
null
)
{
LuaValue
args
=
LuaValue
.
NIL
;
if
(
params
!=
null
)
{
args
=
CoerceJavaToLua
.
coerce
(
params
);
}
ret
=
safetyCall
(
funcName
,
funcLua
,
args
);
}
return
ret
;
}
public
LuaValue
safetyCall
(
String
name
,
LuaValue
func
,
LuaValue
args
){
try
{
return
func
.
call
(
this
.
getScriptLibLua
(),
args
);
return
func
.
call
(
ScriptLoader
.
getScriptLibLua
(),
args
);
}
catch
(
LuaError
error
){
ScriptLib
.
logger
.
error
(
"[LUA] call trigger failed {},{},{}"
,
name
,
args
,
error
.
getMessage
());
return
LuaValue
.
valueOf
(-
1
);
...
...
src/main/java/emu/grasscutter/scripts/ScriptLib.java
View file @
bad85357
...
...
@@ -10,6 +10,7 @@ import emu.grasscutter.scripts.data.SceneRegion;
import
emu.grasscutter.server.packet.send.PacketCanUseSkillNotify
;
import
emu.grasscutter.server.packet.send.PacketGadgetStateNotify
;
import
emu.grasscutter.server.packet.send.PacketWorktopOptionNotify
;
import
io.netty.util.concurrent.FastThreadLocal
;
import
org.luaj.vm2.LuaTable
;
import
org.luaj.vm2.LuaValue
;
import
org.slf4j.Logger
;
...
...
@@ -20,15 +21,24 @@ import java.util.Optional;
public
class
ScriptLib
{
public
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
ScriptLib
.
class
);
private
final
SceneScriptManager
sceneScriptManager
;
public
ScriptLib
(
SceneScriptManager
sceneScriptManager
)
{
this
.
sceneScriptManager
=
sceneScriptManager
;
this
.
currentGroup
=
new
ThreadLocal
<>();
private
final
FastThreadLocal
<
SceneScriptManager
>
sceneScriptManager
;
private
final
FastThreadLocal
<
SceneGroup
>
currentGroup
;
public
ScriptLib
()
{
this
.
sceneScriptManager
=
new
FastThreadLocal
<>();
this
.
currentGroup
=
new
FastThreadLocal
<>();
}
public
void
setSceneScriptManager
(
SceneScriptManager
sceneScriptManager
){
this
.
sceneScriptManager
.
set
(
sceneScriptManager
);
}
public
void
removeSceneScriptManager
(){
this
.
sceneScriptManager
.
remove
();
}
public
SceneScriptManager
getSceneScriptManager
()
{
return
sceneScriptManager
;
// normally not null
return
Optional
.
of
(
sceneScriptManager
.
get
()).
get
();
}
private
String
printTable
(
LuaTable
table
){
...
...
@@ -40,13 +50,11 @@ public class ScriptLib {
sb
.
append
(
"}"
);
return
sb
.
toString
();
}
private
final
ThreadLocal
<
SceneGroup
>
currentGroup
;
public
void
setCurrentGroup
(
SceneGroup
currentGroup
){
logger
.
debug
(
"current {}"
,
currentGroup
);
this
.
currentGroup
.
set
(
currentGroup
);
}
public
Optional
<
SceneGroup
>
getCurrentGroup
(){
return
Optional
.
of
Nullable
(
this
.
currentGroup
.
get
());
return
Optional
.
of
(
this
.
currentGroup
.
get
());
}
public
void
removeCurrentGroup
(){
this
.
currentGroup
.
remove
();
...
...
src/main/java/emu/grasscutter/scripts/ScriptLoader.java
View file @
bad85357
...
...
@@ -29,6 +29,8 @@ public class ScriptLoader {
private
static
ScriptEngineFactory
factory
;
private
static
String
fileType
;
private
static
Serializer
serializer
;
private
static
ScriptLib
scriptLib
;
private
static
LuaValue
scriptLibLua
;
/**
* suggest GC to remove it if the memory is less
*/
...
...
@@ -68,6 +70,10 @@ public class ScriptLoader {
ctx
.
globals
.
set
(
"EventType"
,
CoerceJavaToLua
.
coerce
(
new
EventType
()));
// TODO - make static class to avoid instantiating a new class every scene
ctx
.
globals
.
set
(
"GadgetState"
,
CoerceJavaToLua
.
coerce
(
new
ScriptGadgetState
()));
ctx
.
globals
.
set
(
"RegionShape"
,
CoerceJavaToLua
.
coerce
(
new
ScriptRegionShape
()));
scriptLib
=
new
ScriptLib
();
scriptLibLua
=
CoerceJavaToLua
.
coerce
(
scriptLib
);
ctx
.
globals
.
set
(
"ScriptLib"
,
scriptLibLua
);
}
public
static
ScriptEngine
getEngine
()
{
...
...
@@ -82,6 +88,14 @@ public class ScriptLoader {
return
serializer
;
}
public
static
ScriptLib
getScriptLib
()
{
return
scriptLib
;
}
public
static
LuaValue
getScriptLibLua
()
{
return
scriptLibLua
;
}
public
static
<
T
>
Optional
<
T
>
tryGet
(
SoftReference
<
T
>
softReference
){
try
{
return
Optional
.
ofNullable
(
softReference
.
get
());
...
...
src/main/java/emu/grasscutter/scripts/data/SceneGroup.java
View file @
bad85357
...
...
@@ -10,12 +10,11 @@ import javax.script.Bindings;
import
javax.script.CompiledScript
;
import
javax.script.ScriptException
;
import
java.util.ArrayList
;
import
java.util.Collection
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.stream.Collectors
;
import
static
emu
.
grasscutter
.
Configuration
.
*
;
import
static
emu
.
grasscutter
.
Configuration
.
SCRIPT
;
@ToString
@Setter
...
...
@@ -40,6 +39,7 @@ public class SceneGroup {
private
transient
boolean
loaded
;
// Not an actual variable in the scripts either
private
transient
CompiledScript
script
;
private
transient
Bindings
bindings
;
public
boolean
isLoaded
()
{
return
loaded
;
...
...
@@ -65,13 +65,19 @@ public class SceneGroup {
return
suites
.
get
(
index
-
1
);
}
public
SceneGroup
load
(
int
sceneId
,
Bindings
bindings
){
public
Bindings
getBindings
()
{
return
bindings
;
}
public
SceneGroup
load
(
int
sceneId
){
if
(
loaded
){
return
this
;
}
// Set flag here so if there is no script, we dont call this function over and over again.
setLoaded
(
true
);
this
.
bindings
=
ScriptLoader
.
getEngine
().
createBindings
();
CompiledScript
cs
=
ScriptLoader
.
getScriptByPath
(
SCRIPT
(
"Scene/"
+
sceneId
+
"/scene"
+
sceneId
+
"_group"
+
id
+
"."
+
ScriptLoader
.
getScriptType
()));
...
...
src/main/java/emu/grasscutter/scripts/serializer/LuaSerializer.java
View file @
bad85357
...
...
@@ -87,6 +87,9 @@ public class LuaSerializer implements Serializer {
object
=
(
T
)
constructorCache
.
get
(
type
).
newInstance
();
if
(
table
==
null
){
return
object
;
}
LuaValue
[]
keys
=
table
.
keys
();
for
(
LuaValue
k
:
keys
)
{
try
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment