This repository has been archived by the owner on May 6, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Hexcede
authored
Nov 2, 2019
1 parent
957c9cf
commit 2bca473
Showing
11 changed files
with
605 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"name": "H3x", | ||
"tree": { | ||
"$className": "DataModel" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,235 @@ | ||
-- H3x V1.2 | ||
local Context = {} | ||
|
||
Context.Nil = newproxy() | ||
|
||
local setmetatable = setmetatable | ||
local next = next | ||
local tostring = tostring | ||
local setfenv = setfenv | ||
local loadstring = loadstring | ||
local getfenv = getfenv | ||
local pairs = pairs | ||
local coroutine = coroutine | ||
local assert = assert | ||
local require = require | ||
local script = script | ||
local print = print | ||
local warn = warn | ||
local error = error | ||
local debug = debug | ||
|
||
local _IS_SHUTDOWN = false | ||
local threads = {} | ||
local function captureThread() | ||
local thread = coroutine.running() | ||
threads[thread] = coroutine.status(thread) | ||
|
||
if _IS_SHUTDOWN then | ||
error("The script is shutdown.") -- Kill the thread | ||
end | ||
end | ||
|
||
local function Pointer(...) -- A pointer function. For any arguments you give it it returns them back without using any tables or table functions. | ||
local func | ||
func = coroutine.wrap(function(...) -- Create a coroutine. | ||
captureThread() | ||
coroutine.yield(func) -- Yield the coroutine | ||
return ... | ||
end) | ||
return func(...) | ||
end | ||
|
||
local function wrapFunction(func) | ||
local f = coroutine.wrap(function(...) | ||
captureThread() | ||
local result = function()end | ||
while true do | ||
result = Pointer(func(coroutine.yield(result()))) | ||
end | ||
end) | ||
f() | ||
|
||
return f | ||
end | ||
local context | ||
local runSafe | ||
local communicateShutdown | ||
local function isCFunction(func) | ||
return not pcall(coroutine.wrap, func) | ||
end | ||
local function threadWatch(env) | ||
if env then | ||
local funcs = {} | ||
return setmetatable({}, { | ||
__index = function(_, index) | ||
captureThread() | ||
|
||
local value = env[index] | ||
return value | ||
end, | ||
__newindex = function(_, index, value) | ||
captureThread() | ||
|
||
env[index] = value | ||
end, | ||
__metatable = getmetatable(env) | ||
}) | ||
end | ||
end | ||
|
||
if script.Name == "__Context" then -- We are in a new instance of Context | ||
Context.Libraries = {} | ||
|
||
context = coroutine.wrap(function() | ||
captureThread() | ||
|
||
local id = tostring(context):sub(#"function: "+1) | ||
|
||
local function applyEnv(func, env, mergeMode) | ||
if env then | ||
--env = threadWatch(env) | ||
if not mergeMode then | ||
setfenv(0, env) | ||
else | ||
local cenv = getfenv(0) | ||
|
||
for index, value in pairs(env) do | ||
if value == Context.Nil then | ||
value = nil | ||
end | ||
cenv[index] = value | ||
end | ||
end | ||
end | ||
if func then | ||
setfenv(func, getfenv(0)) | ||
end | ||
end | ||
|
||
setfenv(0, threadWatch(getfenv(0))) | ||
applyEnv(nil, coroutine.yield(getfenv(0))) | ||
|
||
local __context_ = loadstring(coroutine.yield()) | ||
|
||
while true do | ||
applyEnv(__context_, coroutine.yield(wrapFunction(__context_), getfenv(0))) | ||
end | ||
end) | ||
context() | ||
|
||
runSafe = coroutine.wrap(function() | ||
captureThread() | ||
|
||
local func | ||
while true do | ||
func = wrapFunction(coroutine.yield(func)) | ||
end | ||
end) | ||
runSafe() | ||
|
||
communicateShutdown = coroutine.wrap(function() | ||
_IS_SHUTDOWN = true | ||
|
||
for thread, oldStatus in pairs(threads) do | ||
spawn(function() | ||
pcall(function() | ||
local steps = 0 | ||
while coroutine.status(thread) ~= "dead" do -- Suspended, running, or normal. | ||
if steps == 100 then | ||
warn("A sandboxed thread may be inifitely yielding. Will try to invoke an error within ~30 seconds (900 resumes).") | ||
elseif steps > 100 and steps < 1000 then | ||
wait() | ||
elseif steps >= 1000 then | ||
warn("Failed to kill the thread allowing the thread to continue.") | ||
return true | ||
end | ||
|
||
local success = pcall(function() | ||
coroutine.resume(thread) | ||
steps = steps + 1 | ||
end) | ||
if not success then | ||
wait() | ||
end | ||
end | ||
end) | ||
end) | ||
end | ||
end) | ||
end | ||
Context.ThreadWatcherImplemented = false -- Ignore me | ||
|
||
Context.Pointer = Pointer -- For external use | ||
function Context:Create(code, env, mergeMode) | ||
local scr = script:Clone() -- Make a new Context script | ||
scr.Name = "__Context" -- Signal to this script that it will be an instance of Context. | ||
local ctx = require(scr) -- Require the new instance | ||
|
||
if code then | ||
assert(typeof(code) == "string", "The provided code must be a string.") | ||
ctx:Load(code, env, mergeMode) | ||
end | ||
|
||
return ctx | ||
end | ||
|
||
function Context:Load(code, env, mergeMode) | ||
assert(context, "Invalid context.") | ||
self:SetEnvironment(env, mergeMode) -- Set the environment | ||
Context.__context, Context.environment = context(code) -- Compile code and set the context | ||
return Context.__context -- Return the context | ||
end | ||
|
||
function Context:Execute(...) | ||
assert(context, "Invalid context.") | ||
assert(Context.__context, "Context isn't loaded.") | ||
local ptr = Pointer(Context.__context(...)) -- Create pointer for return arguments | ||
Context.__context, Context.environment = context() -- Regenerate context | ||
return ptr() -- Get pointer value | ||
end | ||
|
||
function Context:GetEnvironment() | ||
assert(context, "Invalid context.") | ||
|
||
return Context.environment | ||
end | ||
|
||
function Context:SetEnvironment(env, mergeMode) | ||
assert(context, "Invalid context.") | ||
Context.__context, Context.environment = context(env, mergeMode) -- Set the new context | ||
end | ||
|
||
function Context:GetFunction() | ||
assert(Context.__context, "Invalid context") | ||
return Context.__context | ||
end | ||
|
||
function Context:InjectFunction(func) | ||
assert(context, "Invalid context.") | ||
return runSafe(func) | ||
end | ||
|
||
function Context:AddLibrary(name, lib) | ||
assert(context, "Invalid context.") | ||
Context.Libraries[name] = lib | ||
end | ||
|
||
function Context:RemoveLibrary(name) | ||
Context.Libraries[name] = nil | ||
end | ||
|
||
function Context:Destroy() | ||
if not _IS_SHUTDOWN then | ||
setmetatable(Context, {__mode = "kv"}) | ||
pcall(function() | ||
self:GetEnvironment()() -- Gc environment | ||
end) | ||
self:SetEnvironment({}) | ||
context = nil | ||
runSafe = nil | ||
communicateShutdown() | ||
end | ||
end | ||
|
||
return Context |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
return {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
local Shared = require(script:WaitForChild("Shared")) | ||
|
||
while true do | ||
Shared.DispatchEvent = Shared.DispatchEvent or Instance.new("BindableEvent") | ||
local argPtr = Shared.DispatchEvent.Event:Wait() | ||
if Shared.DispatchFunction and Shared.CompleteEvent then | ||
coroutine.wrap(function() | ||
Shared.CompleteEvent:Fire(Shared.DispatchFunction(argPtr())) | ||
end)() | ||
script.Disabled = true | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
-- H3x V1.2 | ||
local Context = require(script.Parent:WaitForChild("Context")) | ||
local Dispatch = script:WaitForChild("Dispatch") | ||
local Runner = {} | ||
|
||
function Runner:LoadFunction(func, ctx) | ||
assert(func, "Please provide a function to load.") | ||
assert(typeof(func) == "function", "Provided value isn't a function.") | ||
local Script = {} | ||
local newScript = Dispatch:Clone() | ||
|
||
local Shared = require(newScript:WaitForChild("Shared")) | ||
Shared.Context = ctx | ||
|
||
Script.ScriptInstance = newScript | ||
Script.Shared = Shared | ||
|
||
if ctx then | ||
Script.Context = ctx | ||
ctx.TargetScript = Script | ||
end | ||
|
||
Script.TargetFunction = func | ||
function Script:Start(...) | ||
return Runner:StartScript(self, ...) | ||
end | ||
function Script:Stop() | ||
return Runner:StopScript(self) | ||
end | ||
|
||
newScript.Parent = script | ||
return Script | ||
end | ||
|
||
function Runner:LoadScript(scr, env, mergeMode) | ||
assert(scr, "Please provide a script.") | ||
assert(scr.IsA and scr:IsA("Script"), "Provided value isn't a Script instance.") | ||
|
||
assert(pcall(function() | ||
return scr.Source | ||
end), "The Runner cannot load scripts in this context. (Doesn't have permission to script source)") | ||
|
||
local ctx = Context:Create() | ||
ctx:Load(scr.Source, env, mergeMode) | ||
|
||
return Runner:LoadContext(ctx) | ||
end | ||
|
||
function Runner:LoadContext(ctx) | ||
assert(ctx, "Please provide a Context.") | ||
|
||
return Runner:LoadFunction(ctx:GetFunction(), ctx) | ||
end | ||
|
||
function Runner:StopScript(scr) | ||
if typeof(scr) == "Instance" then | ||
scr = {ScriptInstance = scr} | ||
end | ||
assert(typeof(scr.ScriptInstance) == "Instance" and scr.ScriptInstance:IsA("Script"), "Not a valid script.") | ||
scr.ScriptInstance.Disabled = true | ||
end | ||
|
||
function Runner:StartScript(scr, ...) | ||
if typeof(scr) == "Instance" then | ||
scr = {ScriptInstance = scr} | ||
end | ||
assert(typeof(scr.ScriptInstance) == "Instance" and scr.ScriptInstance:IsA("Script"), "Not a valid script.") | ||
local Shared = scr.Shared | ||
|
||
local argPtr = Context.Pointer(...) -- Used to performantly pass arguments | ||
Shared.CompleteEvent = Shared.CompleteEvent or Instance.new("BindableEvent") | ||
Shared.DispatchEvent = Shared.DispatchEvent or Instance.new("BindableEvent") | ||
Shared.DispatchFunction = scr.TargetFunction | ||
|
||
scr.ScriptInstance.Disabled = false -- Enable the script | ||
spawn(function() | ||
Shared.DispatchEvent:Fire(argPtr) -- Dispatch the script | ||
end) | ||
local returnPtr = Context.Pointer(Shared.CompleteEvent.Event:Wait()) -- Used to performantly (and easily) store return values | ||
|
||
return returnPtr() | ||
end | ||
|
||
return Runner |
Oops, something went wrong.