Привет, знатокам Warcraft! Нужна ваша помощь, чтобы спасти функционал карты.
Есть код, позволяющий по нажатию "space" перевести камеру игрока i на позицию юнита udg_Hero[i], где i - номер игрока (i = 0, 1 или 2).
Проблема в том, что в достаточно долгосрочной перспективе (минимум часа через 2-3, с учётом ежесекундного исполнения триггера), этот код приводит к рассинхронизации. Т.е. в какой-то момент, при выполнении этого куска кода (проверено JassSpy), одного из игроков выбрасывает.
Вопросы.
1) В чём причины рассинхронизации, если внутри блока if GetLocalPlayer() == Player(i) then ... endif не создаются динамические объекты.
2) Есть ли наработки для альтернативного решения перевода камеры по space? (обязательно без мемхака)
3) Можно ли задавать SetCameraQuickPosition(x,y) естественным образом без триггеров, т.е. как-то симулировать события, приводящие к гарантированной установке этого флага в нужном месте в нужный момент для нужного игрока.
Спасибо.
Версия Warcraft 1.26a
function Trig_CameraSystem_Actions takes nothing returns nothing
    local real x
    local real y
    local integer i=0
    loop
        if udg_Hero[i]!=null then
            set x=GetUnitX(udg_Hero[i])
            set y=GetUnitY(udg_Hero[i])
            if GetLocalPlayer() == Player(i) then
                call SetCameraQuickPosition(x,y)
                call SetCameraQuickPosition(x,y)
                call SetCameraQuickPosition(x,y)
                call SetCameraQuickPosition(x,y)
                call SetCameraQuickPosition(x,y)
                call SetCameraQuickPosition(x,y)
            endif
        endif
        exitwhen i==2
        set i=i+1
    endloop
endfunction

//===========================================================================
function InitTrig_CameraSystem takes nothing returns nothing
    set gg_trg_CameraSystem = CreateTrigger(  )
    call TriggerRegisterTimerEvent( gg_trg_CameraSystem, 1.00, true )
    call TriggerAddAction( gg_trg_CameraSystem, function Trig_CameraSystem_Actions )
endfunction
Файлы, где происходит десинк.
Сохранение игрок 1:
Сохранение игрок 2:
Карта:

Принятый ответ

По возможности убери все способности на порчу, в коде намёков на десинки не увидел.
`
ОЖИДАНИЕ РЕКЛАМЫ...
0
37
4 года назад
Отредактирован ScorpioT1000
0
Этот код не вызывает десинх, покажите другой, с пробелом

Хотя если разве что баг в рефордже
А зачем столько раз вызывать одну функцию?
0
22
4 года назад
0
ScorpioT1000:
Этот код не вызывает десинх, покажите другой, с пробелом

Хотя если разве что баг в рефордже
А зачем столько раз вызывать одну функцию?
Это и есть весь код. SetCameraQuickPosition устанавливает позицию, куда переключится камера, если будет нажат пробел. У SetCameraQuickPosition есть в буфере несколько позиций. Если несколько подряд раз его исполнить, то весь буфер перепишется.
2
37
4 года назад
2
Я уже понял, у меня две версии - либо близзы что-то сломали в рефордже, либо просто какой-то косяк или утечка, связанная с записью повторов
Может, ты вообще буфер переполняешь и там не 6 позиций. Попробуй сделать в периоде 0.005 и посмотри, как быстро десинкнет
0
27
4 года назад
0
ScorpioT1000,
Версия Warcraft 1.26a
Разве рефордж считают версией не 1.31+?
1
32
4 года назад
Отредактирован Берги
1
Разве рефордж считают версией не 1.31+?
Рефорджем считаются версии 1.32.0+, просто для ScorpioT1000, не существует других варкрафтов...
И всегда можно обвинять реф, что в нём что-то поломали, а что игра 2003 года с тонной багов никто не хочет признавать, Она не расчитана на 2-3 часа игры в принципе. Если вы видели как играли в игру какую-то (Название вашей любимой игры) карту и по 10 часов и по 20. Значит она была крайне простой или "удачно" написанной. (не буду ничего говорить про скилл китайцев/корейцев, они гавнокодеры как и мы все здесь). 2-3 часа для кастомки и так мега супер хороший результат.
0
22
4 года назад
Отредактирован makkad
0
ScorpioT1000:
утечка, связанная с записью повторов
Спасибо за наводку, поищу решение здесь. Такое встречалось где-нибудь? Если прописать DoNotSaveReplay() в карту то её стабильность может повыситься?
Но в итоге, мне кажется, причину тут не найти. Вероятно нужно искать альтернативное решение.
Возможно, как нибудь можно максимально сихронизировать выполняемые функции у игроков в рамках этой задачи? Т.е. чтобы порядок выполнения функций был одинаков у всех игроков. И раз он вылетал на выполнении функции GetLocalPlayer(), то уменьшить число вызовов этой функции. Значение локалок же может быть разным у разных игроков? Например, так:
function Trig_CameraSystem_Actions takes nothing returns nothing
    local real x
    local real y
    local integer i=GetPlayerId(GetLocalPlayer())
    if udg_Hero[i]!=null then
        set x=GetUnitX(udg_Hero[i])
        set y=GetUnitY(udg_Hero[i])
        call SetCameraQuickPosition(x,y)
        call SetCameraQuickPosition(x,y)
        call SetCameraQuickPosition(x,y)
        call SetCameraQuickPosition(x,y)
        call SetCameraQuickPosition(x,y)
        call SetCameraQuickPosition(x,y)
     endif
endfunction
0
17
4 года назад
0
makkad, запустил карту с вашим кодом в мультиплеере в нескольких окнах. Три часа - проблем нет. Скиньте тестовую карту в которой баг воспроизводится
0
22
4 года назад
0
Vlod, Да. Спасибо за тест. У меня у самого на чистой карте только с этим кодом не воспроизводится, так бы прикрепил карту. Даже на грязной карте не каждый раз и не на всех системах. Но имеются сохранения, где происходит гарантированный вылет через секунд 30. Там играли уже 14 часов, но первый рассинхрон из за этой ошибки был через 2 часа. JassSpy указывает на это место.
Ещё странно, что размер файлов сохранений у игроков значительно отличаются.

Вообщем, спасибо за хорошие советы отключить запись реплеев и минимизировать число вызовов GetLocalPlayer().
Загруженные файлы
1
16
4 года назад
1
Bergi_Bear:
И всегда можно обвинять реф, что в нём что-то поломали, а что игра 2003 года с тонной багов никто не хочет признавать, Она не расчитана на 2-3 часа игры в принципе. Если вы видели как играли в игру какую-то (Название вашей любимой игры) карту и по 10 часов и по 20. Значит она была крайне простой или "удачно" написанной. (не буду ничего говорить про скилл китайцев/корейцев, они гавнокодеры как и мы все здесь). 2-3 часа для кастомки и так мега супер хороший результат.
шта?
эта игра поддерживает сейв-лоад, имеет защиту от накопления ошибки float в виде 300-секундных "актов". Она способна играть столько, сколько сможет обеспечить программист триггеров, и у неё, в отличие от д2, тайминги появления нейтралов, рун, крипов не будут съезжать. 10 часов - это средняя сессия в какой-нибудь варкрафтовской ORPG средней руки.
3
32
4 года назад
3
шта?
сейчас бы при игре в варкрафт больше часа на сессию тратить в 2020
0
37
4 года назад
Отредактирован ScorpioT1000
0
Ща в вов столько в рейды не ходят, хз что вы там выдумываете)
P.s. какие накопления ошибки float?
0
16
4 года назад
0
я ж написал про д2 и тайминги, которые съезжают в длинных играх (60+)
щас бы думать, что именно вы - целевая аудитория тех игр, о которых рассуждаете, и лучше знаете среднюю сессию
0
37
4 года назад
Отредактирован ScorpioT1000
0
Пообщались в дискорде и пришли к выводу, что юзать ieee float32 в таймерах - криворукость разрабов, в ос юзаются int микросекунды.
В других случаях проблема бы прокатила из-за float64, но не в 32 битном вц3. Про доту ничего не скажу, не запускал ни разу в жизни.
Что касается автора, результат с периодом 0.005 так и не получил
0
22
4 года назад
Отредактирован makkad
0
Что касается автора, результат с периодом 0.005 так и не получил
Результат отрицательный. Проблем не было. Проблема только при ''грязной игре''. Вот тут расснихрон через 30 сек примерно:
Сохранение игрок 1:
Сохранение игрок 2:
Карта:

Проблема похоже всё-же в том, что накопился какой-то рассинхрон из-за разности времени исполнения функций. Не знаю, как это возможно. Но думаю, если отключить запись реплеев и сделать функцию симметричной для всех игроков (т.е. сделать одинаковый порядок выполнения функций для разных машин), будет легче. Спасибо за наводки.

Просто сейчас порядок такой.
Игрок 1:
GetUnitX() -> GetUnitY() -> GetLocalPlayer() -> SetCameraQuickPosition(x,y) ... -> GetUnitX() -> GetUnitY() -> GetLocalPlayer()
Игрок 2:
GetUnitX() -> GetUnitY() -> GetLocalPlayer() -> GetUnitX() -> GetUnitY() -> GetLocalPlayer() -> SetCameraQuickPosition(x,y) ...
Можно более оптимально переписать код, как здесь xgm.guru/p/wc3/Rassinkhron-ot-GetLocalPlayer---SetCameraQuickPos... и тогда у всех игроков будет порядок:
GetLocalPlayer() -> GetUnitX() -> GetUnitY() -> SetCameraQuickPosition(x,y) ...
Это, наверное, позволит Warcraft не форсировать desync при выполнении этого кода,.
0
28
4 года назад
0
makkad, скрипт кинь. Файл - экспортировать скрипт.
0
22
4 года назад
0
PT153:
makkad, скрипт кинь. Файл - экспортировать скрипт.
Могу, но там огромная карта. В любом случае, jassspy указывет на это место.
0
28
4 года назад
0
makkad, что за jassspy? И если можешь, то чего не кинул?
0
22
4 года назад
0
PT153:
makkad, что за jassspy? И если можешь, то чего не кинул?
Пока нет доступа к компьютеру к файлу.
Для проверки кода подойдёт программа UnrealJassSpy www.hiveworkshop.com/threads/unreal-jass-spy-1-26a.244384
Кидаешь её файлы в папку с игрой, запускаещь игру, ждешь внедрения (жмешь ок), запускаешь карту. Потом в логах JassSpy.txt смотришь на каком месте у тебя прервалась игра.
0
37
4 года назад
Отредактирован ScorpioT1000
0
Так это для фаталов, а не десинков. Десинк происходит не сразу на той же инструкции
Проверить легко - убери именно этот код из карты и она продолжит десинкаться
0
28
4 года назад
0
Порча в карте есть?
0
22
4 года назад
0
ScorpioT1000:
Так это для фаталов, а не десинков. Десинк происходит не сразу на той же инструкции
Проверить легко - убери именно этот код из карты и она продолжит десинкаться
Достаточно мгновенно и стабильно, на этой инструкции плюс минус две функции. Плюс есть триггер, который включается при выходе игрока, и на второй машине, которая остаётся в игре, он включается сразу после этой функции.

PT153:
Порча в карте есть?
Да. Достаточно много.

Спасибо всем за ответы. Да, буду в том чмсле проверять и без этого кода. Ошибка редко ловится с нуля и невоспроизводима. Пока стабильно есть только те сохранения в той конкретной игре и версии, где происходит этот десинк.
Мне кажется, причину найти будет невозможно. Но у меня хорошее предчувствие уже по имеющимся советам оптимизации. Скорее больше хотелось узнать про альтернативы.
То что это может быть глюком записи реплея говорит следующее 1) В реплеях действительно похоже сохраняются все позиции CameraQuickPosition 2) Разный размер файлов сохранений у игроков 3) Отключение записи реплеев зрительно немного повысило производительность в мультиплеере
0
28
4 года назад
Отредактирован PT153
0
Мне кажется, причину найти будет невозможно.
Ты код скинь. Как это сделать, я уже сказал. Много, не много - не важно, во всех текстовых редакторах есть поиск.
Файл - экспортировать скрипт.
Да. Достаточно много.

Был случай.
Строению даётся способность "Порча" во время игры. После того как для любого юнита вызывается SetUnitPositionLoc, происходит десинхронизация.
0
22
4 года назад
0
PT153,
Спасибо за инфу. Но нет, в данном случае юнитам во время игры порчу не давал.
Код карты прикрепил.
Загруженные файлы
1
28
4 года назад
1
По возможности убери все способности на порчу, в коде намёков на десинки не увидел.
Принятый ответ
0
29
4 года назад
0
у неё, в отличие от д2, тайминги появления нейтралов, рун, крипов не будут съезжать
По-моему это уже пофиксили. Но я не думаю, что это было из-за накопления ошибки флоатов в привычном понимании, а скорее из-за обычной логической ошибки в скедулинге событий из-за нецелого деления круглых минут на время тика.
Чтобы оставить комментарий, пожалуйста, войдите на сайт.