I am going to be very, very diplomatic, or try to. This engine is bad. Like, really bad. The only thing this offers is the synthizer sound pool, and even then this could be done more cleanly.
I'll go down the list:
So first, the supposed encryption function maintains a constant IV. I'm not an expert on Cryptography, but I am positive that this is really, really bad. Check this out, the answer in particular, to get a bit more info on what this is and why should you care. But... fine.
Throughout the code, the employed except statements are mostly vague and often silently fail. It is very common to see a "except: pass" within the engine, which can be kind of frustrating when debugging. Also, this is a wrapper over os.mkdir, which kind of defeats the whole purpose of the function. It's much more easier for me to go thus:
if not os.path.isdir(path):
That, unfortunately, summarizes about half of the "engine".
find_recursive can be easily surpassed with regex or your own loop, again.
file_copy and file_delete are perhaps the only functions one does not have an easy access to in Python. file_put_contents is just an unneeded wrapper once again, and the encrypt and decrypt functions are flawed do to the constant IV. Savedata class could be useful I suppose, but I personally feel like this is too narrow in scope. One would have a hard time saving game state or anything of substance using this approach.
From now on, I'll provide comments for the files as a whole.
map.py and its type_2d and type_3d serve zero purpose. Besides employing kwargs 99% of the time, something which causes code repetition, the falsy typing of the map serves only to confuse the reader and doesn't allow it to gain more features. Why not use positional args and provide default values?
menu3d.py is only useful until you realize that you can't do any kind of design pattern with it because, surprise, it takes control of your main loop.
sound3d.py serves as a painful reminder that this was taken from BGT
while self.get_item(id)!=0 and tries<500:
if tries>=500: return -1
This speaks of the lack of understanding about what classes are. Why not discard the idea of slots entirely and return newly-created objects and change the update functions to work with them directly? If you are that intent on using IDs, why not have an index which you increment every time you append the sound to the list? You can then use said value as the new ID and mitigate the, although insignificant, chance of your get_id function failing. Your fade functions once again steal the main loop. What if I want to do something else while the sound fades out? I'd have to modify the engine to support callbacks... but at that point I just won't use it.
Also, what do these lines do? Do they actually work as expected?
i.handle.source.position=(x,z,y) #Do you have coordinates switched?
What is this magical 4 constant?
Speech.py worths mentioning because it once again, provides a wrapper over a wrapper which serves absolutely zero purpose
Timer and window -- the essential components of your engine -- are lifted straight from Lucia, which brings me to the point of this post: Why not offer what you've made as contributions to the Lucia repo? Calling this "tools" is a stretch especially when so much of the essential features are from another engine. Please, do us all a favor, clean and merge your actual creations (excluding data.py for the reasons mentioned above) to the Lucia repository.
TLDR: Avoid this and use Lucia instead if you must... or just switch directly to pygame and cytolk. It's not hard, folks.