Merge pull request #2333 from Owain94/scriptvmevents
mixins: ScriptVM events
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018 Abex
|
* Copyright (c) 2018 Abex
|
||||||
|
* Copyright (c) 2020 ThatGamerBlue
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@@ -24,9 +25,13 @@
|
|||||||
*/
|
*/
|
||||||
package net.runelite.mixins;
|
package net.runelite.mixins;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Stack;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import net.runelite.api.Client;
|
import net.runelite.api.Client;
|
||||||
|
import static net.runelite.api.Opcodes.INVOKE;
|
||||||
|
import static net.runelite.api.Opcodes.RETURN;
|
||||||
import static net.runelite.api.Opcodes.RUNELITE_EXECUTE;
|
import static net.runelite.api.Opcodes.RUNELITE_EXECUTE;
|
||||||
import net.runelite.api.events.ScriptCallbackEvent;
|
import net.runelite.api.events.ScriptCallbackEvent;
|
||||||
import net.runelite.api.events.ScriptPostFired;
|
import net.runelite.api.events.ScriptPostFired;
|
||||||
@@ -55,10 +60,21 @@ public abstract class ScriptVMMixin implements RSClient
|
|||||||
@Inject
|
@Inject
|
||||||
private static int currentScriptPC;
|
private static int currentScriptPC;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private static ScriptPostFired deferredEvent = null;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private static Stack<Integer> scriptIds = new Stack<>();
|
||||||
|
|
||||||
// Call is injected into runScript by the ScriptVM raw injector
|
// Call is injected into runScript by the ScriptVM raw injector
|
||||||
@Inject
|
@Inject
|
||||||
static boolean vmExecuteOpcode(int opcode)
|
static boolean vmExecuteOpcode(int opcode)
|
||||||
{
|
{
|
||||||
|
if (deferredEvent != null)
|
||||||
|
{
|
||||||
|
client.getCallbacks().post(ScriptPostFired.class, deferredEvent);
|
||||||
|
deferredEvent = null;
|
||||||
|
}
|
||||||
if (opcode == RUNELITE_EXECUTE)
|
if (opcode == RUNELITE_EXECUTE)
|
||||||
{
|
{
|
||||||
assert currentScript.getInstructions()[currentScriptPC] == RUNELITE_EXECUTE;
|
assert currentScript.getInstructions()[currentScriptPC] == RUNELITE_EXECUTE;
|
||||||
@@ -105,6 +121,21 @@ public abstract class ScriptVMMixin implements RSClient
|
|||||||
client.getCallbacks().post(ScriptCallbackEvent.class, event);
|
client.getCallbacks().post(ScriptCallbackEvent.class, event);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
else if (opcode == INVOKE)
|
||||||
|
{
|
||||||
|
int id = currentScript.getIntOperands()[currentScriptPC];
|
||||||
|
scriptIds.push(id);
|
||||||
|
ScriptPreFired event = new ScriptPreFired(id);
|
||||||
|
event.setScriptEvent(null);
|
||||||
|
client.getCallbacks().post(ScriptPreFired.class, event);
|
||||||
|
}
|
||||||
|
else if (opcode == RETURN)
|
||||||
|
{
|
||||||
|
if (scriptIds.size() > 1) // let the runScript method handle the final script
|
||||||
|
{
|
||||||
|
deferredEvent = new ScriptPostFired(scriptIds.pop()); // fire the event when we've left the script
|
||||||
|
}
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,36 +153,48 @@ public abstract class ScriptVMMixin implements RSClient
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
ScriptPreFired preFired = new ScriptPreFired(-1);
|
||||||
|
preFired.setScriptEvent(event);
|
||||||
|
client.getCallbacks().post(ScriptPreFired.class, preFired);
|
||||||
|
|
||||||
((JavaScriptCallback) arguments[0]).run(event);
|
((JavaScriptCallback) arguments[0]).run(event);
|
||||||
|
|
||||||
|
ScriptPostFired postFired = new ScriptPostFired(-1);
|
||||||
|
client.getCallbacks().post(ScriptPostFired.class, postFired);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e) // wont catch assertions
|
||||||
{
|
{
|
||||||
client.getLogger().error("Error in JavaScriptCallback", e);
|
client.getLogger().error("Error in JavaScriptCallback", e);
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
try
|
|
||||||
{
|
{
|
||||||
if (event.getArguments() != null && event.getArguments().length > 0)
|
try
|
||||||
{
|
{
|
||||||
ScriptPreFired scriptPreFired = new ScriptPreFired((Integer) event.getArguments()[0]);
|
scriptIds.push((Integer) event.getArguments()[0]); // this is safe because it will always be the script id
|
||||||
scriptPreFired.setScriptEvent(event);
|
|
||||||
client.getCallbacks().post(ScriptPreFired.class, scriptPreFired);
|
ScriptPreFired preFired = new ScriptPreFired(scriptIds.peek()); // peek doesn't remove the top item
|
||||||
|
preFired.setScriptEvent(event);
|
||||||
|
client.getCallbacks().post(ScriptPreFired.class, preFired);
|
||||||
|
|
||||||
|
rs$runScript(event, maxExecutionTime);
|
||||||
|
|
||||||
|
if (!scriptIds.empty())
|
||||||
|
{
|
||||||
|
ScriptPostFired postFired = new ScriptPostFired(scriptIds.pop()); // hopefully the stack should be dry at this point
|
||||||
|
assert scriptIds.empty() : "Script ID stack should be empty! Contains: " + getAllScriptIds();
|
||||||
|
client.getCallbacks().post(ScriptPostFired.class, postFired);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
finally
|
||||||
rs$runScript(event, maxExecutionTime);
|
|
||||||
|
|
||||||
if (event.getArguments() != null && event.getArguments().length > 0)
|
|
||||||
{
|
{
|
||||||
ScriptPostFired scriptPostFired = new ScriptPostFired((Integer) event.getArguments()[0]);
|
currentScript = null;
|
||||||
client.getCallbacks().post(ScriptPostFired.class, scriptPostFired);
|
while (!scriptIds.empty())
|
||||||
|
{
|
||||||
|
scriptIds.pop(); // make sure the stack is empty, something disastrous happened
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
finally
|
|
||||||
{
|
|
||||||
currentScript = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
@@ -165,4 +208,25 @@ public abstract class ScriptVMMixin implements RSClient
|
|||||||
se.setArguments(args);
|
se.setArguments(args);
|
||||||
runScript(se, 5000000);
|
runScript(se, 5000000);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
@Inject
|
||||||
|
private static String getAllScriptIds()
|
||||||
|
{
|
||||||
|
ArrayList<Integer> ids = new ArrayList<>(scriptIds);
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
boolean first = true;
|
||||||
|
for (Object item : ids)
|
||||||
|
{
|
||||||
|
if (first)
|
||||||
|
{
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sb.append(", ");
|
||||||
|
}
|
||||||
|
sb.append(item);
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user