Jump to content

Avoiding Runtime Errors


Maris

Recommended Posts

Let's say there is a critical game function "render":

function SomeClass:render()
	--Game code (safe)
end

 

And you want to inject into it.

As you know, replacing the whole function is bad practice.

Therefore, the injection in your mod will look something like this:

local old_fn = SomeClass.render
SomeClass.render = function(self, ...)
	--Your code (unsafe)
	return old_fn(self, ...)
end

 

The main difficulty is that your code may contain errors with a high chance. And if something goes wrong, the user will receive a ton of red errors or the game will freeze because the function is critical and is called roughly every tick.

 

So you want at least stop spam of errors if something went wrong.

 

There is a solution!

local in_progress = false
local old_fn = SomeClass.render
SomeClass.render = function(self, ...)
	if in_progress then
		return old_fn(self, ...)
	end
	in_progress = true
	--Your code (unsafe)
	in_progress = false
	return old_fn(self, ...)
end

 

Actually, this code was created in order to avoid recursion. But as a side effect, it allows to bypass the storm of errors. If something breaks the mod, then the mod just stops working, and the game continues without further errors.

 

 

 

Edited by Maris
Link to comment
Share on other sites

Okay, let's say you need DOUBLE INJECTION. :)

 

Why would you need this? For example, you are a very neat modder and do not want to load the user's CPU, overwriting common game functions and making permanent injection. One of these functions is getText(). And you want to make temporary ninja injection.

 

So we have to go a more complex way:

local old_getText = nil
local function new_getText(str,...)
	--You code (unsafe!)
	return old_getText(str,...)
end


local in_progress = false
local old_render = SomeClass.render
function SomeClass:render(...) --permanent injection
	if in_progress then
		if old_getText and getText == new_getText then
			getText = old_getText
			old_getText = nil
		end
		return old_render(self, ...)
	end
	old_getText = getText
	getText = new_getText --tempry second injection
	in_progress = true
	local result = old_render(self, ...)
	in_progress = false
	if old_getText then
		getText = old_getText
	end
	return result
end

 

If something goes wrong, your feature just stop working and that's it. No further game errors.

 

P.S. Specific function render() does not return a result (by meaning), so you may omit it in this case. But it's not a mistake. Usually you have to keep the result.

 

 

 

Edited by Maris
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...