
01.06.2025, 16:11
|
|
Постоянный
Регистрация: 05.08.2018
Сообщений: 372
С нами:
4091290
Репутация:
213
|
|
Сообщение от TheLeftExit
Приветы, а можно как-то внутри C++ хука, зарегистрированного в registerChatCommand, асинхронно ждать внутри своего кода?
Допустим, у меня есть такое:
псевдокод:
Код:
SF->getCLEO()->callOpcode("0C8F: samp process_chat_input \"1\"");
// спать 300
SF->getCLEO()->callOpcode("0C8F: samp process_chat_input \"2\"");
// спать 300
SF->getCLEO()->callOpcode("0C8F: samp process_chat_input \"3\"");
На деле код спит полсекунды и затем все три строки в чат одновременно выдаёт (и две из них отлетают антифлудом). Cleo/sampfuncs дают какой-то способ поставить свой код в очередь выполняться через X мс?
Или если я могу сам подождать в соседнем треде, а потом отправить остальной код выполняться в нужный (как Control.Invoke), так ещё лучше.
upd: похоже, я могу спокойно гонять callOpcode из соседнего треда, в котором sleep ничего не блокирует. Вопрос снят
Сообщение от TheLeftExit
Вопрос выше снова актуален. Оказывается, вызов клео из соседних тредов небезопасен; я в одной функции добавил вообщение в чат (AddChatMessage) и запустил тред, который добавляет другое сообщение в чат, и в итоге второе сообщение превратилось в какую-то юникодную букву (вылечилось только комментированием AddChatMessage из кода соседнего треда).
Либо в принципе как-то потоко-безопасно выполнять код, когда игрок нажмёт нужные мне кнопки. Я могу чекать в цикле isKeyPressed/isKeyDown, но непонятно как в C++ это делать и не блокировать игру. В Lua делают wait(0), я полагаю moonloader это интерпретирует как "вернуться к скрипту в следующий фрейм", вот мне надо как-то сделать то же самое в C++.
Изначально использовать клео опкоды в С/C++ - бред, когда у тебя под рукой есть возможность напрямую вызывать методы по адресам. Белиберда у тебя из-за того, что ты пытаешься из двух разных потоков писать/читать в одну область памяти, из-за чего происходит гонка потоков, которая вызывает UB. В обычном случае игра просто должна вылететь. Советую ознакомиться с std::mutex / std::lock_guard, но в твоем случае, можно и одним потоком обойтись, просто написав примитивный таймер на GetTickCount64() (win), либо std::chrono (под любую платформу)
|
|
|