|
Cheat Engine The Official Site of Cheat Engine
|
View previous topic :: View next topic |
Author |
Message |
TheyCallMeTim13 Wiki Contributor Reputation: 50
Joined: 24 Feb 2017 Posts: 976 Location: Pluto
|
Posted: Sat Mar 24, 2018 8:51 am Post subject: Wait on Async memory record thread. |
|
|
Is there a way to wait on an async memory record's thread?
_________________
|
|
Back to top |
|
|
MateeJr GT Advanced Cheater Reputation: 0
Joined: 24 Dec 2017 Posts: 66
|
Posted: Sat Mar 24, 2018 9:00 am Post subject: |
|
|
Yes
_________________
Hi Lynxz Gaming |
|
Back to top |
|
|
panraven Grandmaster Cheater Reputation: 54
Joined: 01 Oct 2008 Posts: 941
|
Posted: Sat Mar 24, 2018 9:13 am Post subject: |
|
|
try check AsyncProcessing,
note that Async can be false, ie changed during async execution by user or by script.
_________________
- Retarded. |
|
Back to top |
|
|
TheyCallMeTim13 Wiki Contributor Reputation: 50
Joined: 24 Feb 2017 Posts: 976 Location: Pluto
|
Posted: Sat Mar 24, 2018 10:00 am Post subject: |
|
|
panraven wrote: | try check AsyncProcessing,
note that Async can be false, ie changed during async execution by user or by script. |
So it tried:
Code: | while mr.Async and mr.AsyncProcessing do
sleep(1)
end |
But it didn't work (EDIT: seems to wait endlessly). And if the memory record is Async then it breaks the order. (EDIT: at lest with nested records.)
Lines 176 and 210:
Full code (records the table's memory records states' and sets them latter):
Code: |
local NAME = 'I2 Cheat Engine Table State'
local CLASS_NAME = 'I2CETState'
local VERSION = '1.0.2'
local AUTHOR = 'Matt Irwin; [email protected]'
local LICENSE = [=[MIT License
Copyright (c) 2017 Matt Irwin
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sub-license, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
]=]
local format = string.format
local strE = string.empty or STRING_EMPTY or ''
local t = translate
I2CETState = {
Name = NAME,
ClassName = CLASS_NAME,
Version = VERSION,
Author = AUTHOR,
License = LICENSE,
DefaultState = 'default',
SaveFileName = 'I2CETState.${StateName}.txt',
UseMemoryRecordDescriptions = false,
LineEnd = '\n',
DisableBeforeLoad = true,
PrintStatus = true,
}
-- local Logger = {
-- LEVELS = {
-- OFF = 0,
-- FATAL = 1,
-- ERROR = 2,
-- WARN = 3,
-- INFO = 4,
-- DEBUG = 5,
-- TRACE = 6
-- },
-- }
-- for k, v in pairs(Logger.LEVELS) do
-- -- Logger[k:lower()] = function( ... ) return end
-- -- Logger[k:lower() .. 'f'] = function( ... ) return end
-- Logger[k:lower()] = function(msg, ex) return print(msg, ex) end
-- Logger[k:lower() .. 'f'] = function(msg, ... ) return print(string.format(msg, ... )) end
-- end
local Logger = Logger
if Logger == nil then
if type(CETrequire) == 'function' then
Logger = CETrequire('I2CETLogger')
else
Logger = require('I2CETLogger')
end
Logger.LogName = 'CETstate'
end
if type(CETrequire) == 'function' then
I2CEHelpers = CETrequire('I2CEHelpers')
else
I2CEHelpers = require('I2CEHelpers')
end
local function split(s, delimiter)
return I2CEHelpers.split(s, delimiter)
end
local function interp(s, tbl)
return I2CEHelpers.interp(s, tbl)
end
function I2CETState.saveTableState(stateName)
Logger.trace()
local le = I2CETState.LineEnd
if stateName == nil then
stateName = I2CETState.DefaultState
end
local fileName = interp(I2CETState.SaveFileName, { StateName = stateName } )
local fileStr = strE
for i = 0, AddressList.Count - 1 do
local mr = AddressList.getMemoryRecord(i)
if mr.Description ~= '_[ I2CETState ]_' and mr.Description:sub(0, 16) ~= 'Save Table State' then
if mr.Active then
local id = tostring(mr.ID)
if I2CETState.UseMemoryRecordDescriptions then
id = mr.Description
end
fileStr = fileStr .. id .. le
end
end
end
local f, err = io.open(fileName, 'w')
if err then
Logger.errorf('The file could not be opened, "%s", %s', fileName, err)
elseif f and not err then
f:write(fileStr)
f:close()
end
end
function I2CETState.loadTableState(stateName)
Logger.trace()
if I2CETState.PrintStatus and Logger.Level <= Logger.LEVELS.WARN then
getLuaEngine().show()
end
local le = I2CETState.LineEnd
if stateName == nil then
stateName = I2CETState.DefaultState
end
if I2CETState.PrintStatus and Logger.Level <= Logger.LEVELS.WARN then
print(format('Setting Table State: %s', stateName))
end
local fileName = interp(I2CETState.SaveFileName, { StateName = stateName } )
Logger.debugf('Using state file name: "%s"', fileName)
local fileStr = nil
local f, err = io.open(fileName, 'r')
if err then
Logger.infof('The local file could not be opened, "%s", %s', fileName, err)
local tableFile = findTableFile(fileName)
if tableFile == nil then
Logger.warnf('file not found, "%s"', fileName)
return
end
local stream = tableFile.getData()
local bytes = stream.read(stream.Size)
for i = 1, #bytes do
if fileStr == nil then
fileStr = strE
end
fileStr = fileStr .. string.char(bytes[i])
end
elseif f and not err then
fileStr = f:read('*all')
f:close()
else
Logger.errorf('The file could not be opened, "%s"', fileName)
end
if I2CETState.DisableBeforeLoad then
for i = AddressList.Count - 1, 0, -1 do
local mr = AddressList.getMemoryRecord(i)
if mr.Description ~= '_[ I2CETState ]_' and mr.Description:sub(0, 16) ~= 'Save Table State' then
if mr.Active then
Logger.infof('Disabling memory record: %d, %d, "%s"', mr.Index, mr.ID, mr.Description)
if I2CETState.PrintStatus and Logger.Level <= Logger.LEVELS.WARN then
local des = mr.Description--:gsub('_[ ', strE):gsub(' ]_', strE):gsub('-[ ', strE):gsub(' ]-', strE):gsub(' ()->', strE)
print(format('Disabling: %s', des))
end
if mr.Async then
mr.Async = false
sleep(0)
end
mr.Active = false
-- while mr.Async and mr.AsyncProcessing do
-- sleep(1)
-- end
sleep(0)
end
end
end
sleep(0)
end
if fileStr == nil then
Logger.info('File string empty')
return
end
local lines = split(fileStr, I2CETState.LineEnd)
for i, v in ipairs(lines) do
if v ~= nil and v ~= strE then
local mr = nil
if I2CETState.UseMemoryRecordDescriptions then
mr = AddressList.getMemoryRecordByDescription(v)
else
mr = AddressList.getMemoryRecordByID(tonumber(v))
end
if mr ~= nil then
if not mr.Active then
Logger.infof('Enabling memory record: %d, %d, "%s"', mr.Index, mr.ID, mr.Description)
if I2CETState.PrintStatus and Logger.Level <= Logger.LEVELS.WARN then
local des = mr.Description--:gsub('_[ ', strE):gsub(' ]_', strE):gsub('-[ ', strE):gsub(' ]-', strE):gsub(' ()->', strE)
print(format('Enabling: %s', des))
end
if mr.Async then
mr.Async = false
sleep(0)
end
mr.Active = true
-- while mr.Async and mr.AsyncProcessing do
-- sleep(1)
-- end
sleep(0)
end
end
end
end
if I2CETState.PrintStatus and Logger.Level <= Logger.LEVELS.WARN then
print(format('Table State Set: %s', stateName))
getLuaEngine().hide()
end
end
return I2CETState
|
_________________
|
|
Back to top |
|
|
ParkourPenguin I post too much Reputation: 138
Joined: 06 Jul 2014 Posts: 4275
|
|
Back to top |
|
|
TheyCallMeTim13 Wiki Contributor Reputation: 50
Joined: 24 Feb 2017 Posts: 976 Location: Pluto
|
Posted: Sat Mar 24, 2018 11:20 am Post subject: |
|
|
ParkourPenguin wrote: | If you want to block the main thread, don't execute the script asynchronously. It pretty much defeats the purpose of executing it on a different thread, and there isn't a simple way to check when it's done. The active property will change only if it executes successfully, and the AsyncProcessing property must be changed by the main thread.
The following does not apply to the code you posted above, but if someone is in a rare situation in which blocking the main thread is the best course of action, call checkSynchronize in the wait loop and break when AsyncProcessing is false. This works for CE 6.7, and while I would guess it will work for future versions, I don't believe there's any guarantee.
Memory records also have an OnActivate property that some may find more useful. |
So I started to mess with threads, found "checkSynchronize" but didn't think to use it in the while loop, but that worked. Thank you.
Code: |
mr.Active = false
while mr.Async and mr.AsyncProcessing do
checkSynchronize()
end |
EDIT:
Then added this to get the UI to update:
Code: |
while mr.Async and mr.AsyncProcessing do
checkSynchronize()
MainForm.repaint()
end |
Full Working Code (so far):
Code: |
local NAME = 'I2 Cheat Engine Table State'
local CLASS_NAME = 'I2CETState'
local VERSION = '1.0.3'
local AUTHOR = 'Matt Irwin; [email protected]'
local LICENSE = [=[MIT License
Copyright (c) 2017 Matt Irwin
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sub-license, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
]=]
local format = string.format
local strE = string.empty or STRING_EMPTY or ''
local t = translate
I2CETState = {
Name = NAME,
ClassName = CLASS_NAME,
Version = VERSION,
Author = AUTHOR,
License = LICENSE,
DefaultState = 'default',
SaveFileName = 'I2CETState.${StateName}.txt',
UseMemoryRecordDescriptions = false,
LineEnd = '\n',
DisableBeforeLoad = true,
PrintStatus = false, --true,
}
-- local Logger = {
-- LEVELS = {
-- OFF = 0,
-- FATAL = 1,
-- ERROR = 2,
-- WARN = 3,
-- INFO = 4,
-- DEBUG = 5,
-- TRACE = 6
-- },
-- }
-- for k, v in pairs(Logger.LEVELS) do
-- -- Logger[k:lower()] = function( ... ) return end
-- -- Logger[k:lower() .. 'f'] = function( ... ) return end
-- Logger[k:lower()] = function(msg, ex) return print(msg, ex) end
-- Logger[k:lower() .. 'f'] = function(msg, ... ) return print(string.format(msg, ... )) end
-- end
local Logger = Logger
if Logger == nil then
if type(CETrequire) == 'function' then
Logger = CETrequire('I2CETLogger')
else
Logger = require('I2CETLogger')
end
Logger.LogName = 'CETstate'
end
if type(CETrequire) == 'function' then
I2CEHelpers = CETrequire('I2CEHelpers')
else
I2CEHelpers = require('I2CEHelpers')
end
local function split(s, delimiter)
return I2CEHelpers.split(s, delimiter)
end
local function interp(s, tbl)
return I2CEHelpers.interp(s, tbl)
end
function I2CETState.saveTableState(stateName)
Logger.trace()
if not inMainThread() then
return I2CETState.saveTableStateT(stateName)
end
local le = I2CETState.LineEnd
if stateName == nil then
stateName = I2CETState.DefaultState
end
local fileName = interp(I2CETState.SaveFileName, { StateName = stateName } )
local fileStr = strE
for i = 0, AddressList.Count - 1 do
local mr = AddressList.getMemoryRecord(i)
if mr.Description ~= '_[ I2CETState ]_'
and mr.Description:sub(0, 16) ~= 'Load Table State'
and mr.Description:sub(0, 16) ~= 'Save Table State' then
if mr.Active then
local id = tostring(mr.ID)
if I2CETState.UseMemoryRecordDescriptions then
id = mr.Description
end
fileStr = fileStr .. id .. le
end
end
end
local f, err = io.open(fileName, 'w')
if err then
Logger.errorf('The file could not be opened, "%s", %s', fileName, err)
elseif f and not err then
f:write(fileStr)
f:close()
end
end
local function saveTableStateThread_logError(thread, fileName, err)
Logger.errorf('The file could not be opened, "%s", %s', fileName, err)
checkSynchronize()
thread.terminate()
end
local function saveTableStateThread(thread, stateName)
local le = I2CETState.LineEnd
if stateName == nil then
stateName = I2CETState.DefaultState
end
local fileName = interp(I2CETState.SaveFileName, { StateName = stateName } )
local fileStr = strE
for i = 0, AddressList.Count - 1 do
local mr = AddressList.getMemoryRecord(i)
if mr.Description ~= '_[ I2CETState ]_'
and mr.Description:sub(0, 16) ~= 'Load Table State'
and mr.Description:sub(0, 16) ~= 'Save Table State' then
if mr.Active then
local id = tostring(mr.ID)
if I2CETState.UseMemoryRecordDescriptions then
id = mr.Description
end
fileStr = fileStr .. id .. le
end
end
end
local f, err = io.open(fileName, 'w')
if err then
synchronize(saveTableStateThread_logError, fileName, err)
elseif f and not err then
f:write(fileStr)
f:close()
end
thread.terminate()
end
function I2CETState.saveTableStateT(stateName)
Logger.trace()
createThread(saveTableStateThread, stateName)
end
function I2CETState.loadTableState(stateName)
Logger.trace()
if not inMainThread() then
return I2CETState.loadTableStateT(stateName)
end
if I2CETState.PrintStatus and Logger.Level <= Logger.LEVELS.WARN then
getLuaEngine().show()
end
local le = I2CETState.LineEnd
if stateName == nil then
stateName = I2CETState.DefaultState
end
if I2CETState.PrintStatus and Logger.Level <= Logger.LEVELS.WARN then
print(format('Setting Table State: %s', stateName))
end
local fileName = interp(I2CETState.SaveFileName, { StateName = stateName } )
Logger.debugf('Using state file name: "%s"', fileName)
local fileStr = nil
local f, err = io.open(fileName, 'r')
if err then
Logger.infof('The local file could not be opened, "%s", %s', fileName, err)
local tableFile = findTableFile(fileName)
if tableFile == nil then
Logger.warnf('file not found, "%s"', fileName)
return
end
local stream = tableFile.getData()
local bytes = stream.read(stream.Size)
for i = 1, #bytes do
if fileStr == nil then
fileStr = strE
end
fileStr = fileStr .. string.char(bytes[i])
end
elseif f and not err then
fileStr = f:read('*all')
f:close()
else
Logger.errorf('The file could not be opened, "%s"', fileName)
end
if I2CETState.DisableBeforeLoad then
for i = AddressList.Count - 1, 0, -1 do
local mr = AddressList.getMemoryRecord(i)
if mr.Description ~= '_[ I2CETState ]_'
and mr.Description:sub(0, 16) ~= 'Load Table State'
and mr.Description:sub(0, 16) ~= 'Save Table State' then
if mr.Active then
Logger.infof('Disabling memory record: %d, %d, "%s"', mr.Index, mr.ID, mr.Description)
if I2CETState.PrintStatus and Logger.Level <= Logger.LEVELS.WARN then
print(format('Disabling: %s', mr.Description))
end
mr.Active = false
while mr.Async and mr.AsyncProcessing do
checkSynchronize()
end
sleep(0)
end
end
end
sleep(0)
end
if fileStr == nil then
Logger.info('File string was nil')
return
end
local lines = split(fileStr, I2CETState.LineEnd)
for i, v in ipairs(lines) do
if v ~= nil and v ~= strE then
local mr = nil
if I2CETState.UseMemoryRecordDescriptions then
mr = AddressList.getMemoryRecordByDescription(v)
else
mr = AddressList.getMemoryRecordByID(tonumber(v))
end
if mr ~= nil then
if not mr.Active then
Logger.infof('Enabling memory record: %d, %d, "%s"', mr.Index, mr.ID, mr.Description)
if I2CETState.PrintStatus and Logger.Level <= Logger.LEVELS.WARN then
print(format('Enabling: %s', mr.Description))
end
mr.Active = true
while mr.Async and mr.AsyncProcessing do
checkSynchronize()
end
sleep(0)
end
end
end
end
if I2CETState.PrintStatus and Logger.Level <= Logger.LEVELS.WARN then
print(format('Table State Set: %s', stateName))
getLuaEngine().hide()
end
end
local function loadTableStateThreadSynced(thread, stateName)
Logger.trace()
if I2CETState.PrintStatus and Logger.Level <= Logger.LEVELS.WARN then
getLuaEngine().show()
end
local le = I2CETState.LineEnd
if stateName == nil then
stateName = I2CETState.CurrentStateName or I2CETState.DefaultState
end
if I2CETState.PrintStatus and Logger.Level <= Logger.LEVELS.WARN then
print(format('Setting Table State: %s', stateName))
end
local fileName = interp(I2CETState.SaveFileName, { StateName = stateName } )
Logger.debugf('Using state file name: "%s"', fileName)
local fileStr = nil
local f, err = io.open(fileName, 'r')
if err then
Logger.infof('The local file could not be opened, "%s", %s', fileName, err)
local tableFile = findTableFile(fileName)
if tableFile == nil then
Logger.warnf('file not found, "%s"', fileName)
return
end
local stream = tableFile.getData()
local bytes = stream.read(stream.Size)
for i = 1, #bytes do
if fileStr == nil then
fileStr = strE
end
fileStr = fileStr .. string.char(bytes[i])
end
elseif f and not err then
fileStr = f:read('*all')
f:close()
else
Logger.errorf('The file could not be opened, "%s"', fileName)
end
if I2CETState.DisableBeforeLoad then
for i = AddressList.Count - 1, 0, -1 do
local mr = AddressList.getMemoryRecord(i)
if mr.Description ~= '_[ I2CETState ]_'
and mr.Description:sub(0, 16) ~= 'Load Table State'
and mr.Description:sub(0, 16) ~= 'Save Table State' then
if mr.Active then
Logger.infof('Disabling memory record: %d, %d, "%s"', mr.Index, mr.ID, mr.Description)
if I2CETState.PrintStatus and Logger.Level <= Logger.LEVELS.WARN then
print(format('Disabling: %s', mr.Description))
end
mr.Active = false
while mr.Async and mr.AsyncProcessing do
checkSynchronize()
MainForm.repaint()
end
sleep(0)
end
end
end
sleep(0)
end
if fileStr == nil then
Logger.info('File string was nil')
return
end
local lines = split(fileStr, I2CETState.LineEnd)
for i, v in ipairs(lines) do
if v ~= nil and v ~= strE then
local mr = nil
if I2CETState.UseMemoryRecordDescriptions then
mr = AddressList.getMemoryRecordByDescription(v)
else
mr = AddressList.getMemoryRecordByID(tonumber(v))
end
if mr ~= nil then
if not mr.Active then
Logger.infof('Enabling memory record: %d, %d, "%s"', mr.Index, mr.ID, mr.Description)
if I2CETState.PrintStatus and Logger.Level <= Logger.LEVELS.WARN then
print(format('Enabling: %s', mr.Description))
end
mr.Active = true
while mr.Async and mr.AsyncProcessing do
checkSynchronize()
MainForm.repaint()
end
sleep(0)
end
end
end
end
if I2CETState.PrintStatus and Logger.Level <= Logger.LEVELS.WARN then
print(format('Table State Set: %s', stateName))
getLuaEngine().hide()
end
I2CETState.CurrentStateName = nil
checkSynchronize()
if thread ~= nil and type(thread.terminate) == 'function' then
thread.terminate()
end
end
local function loadTableStateThread(thread, stateName)
synchronize(loadTableStateThreadSynced, stateName)
thread.terminate()
end
function I2CETState.loadTableStateT(stateName)
Logger.trace()
I2CETState.CurrentStateName = stateName
createThread(loadTableStateThread, stateName)
end
return I2CETState
|
_________________
|
|
Back to top |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum You cannot attach files in this forum You can download files in this forum
|
|