Inellok
А если ещё насчёт снапшотов... Я храню один изменяемый приходящими пакетами и второй - неизменный, который уже был отправлен(чтобы если что к нему вернуться, если вдруг какой-то игрок - тормоз). Когда я должен отправить изменяемый снапшот и поставить его на место первого(неизменного, хранящегося для бэкапа на 0.1 секунду назад)?
Snusmumriken
Щтоу?
Snusmumriken
Для сетевой игры, держи на сервере тупо список всех распаршенных сообщений с действиями от клиентов. Это всё что тебе нужно.
Снапшоты делаешь по игровому миру с метками по времени.
Inellok
Отсортированный по временным меткам?
Snusmumriken
Ну конечно.
Snusmumriken
Имеют реальное значение последние секунд пять-десять, остальное можешь в целом отбросить или записать в файл реплея.
Inellok
Мне ведь ещё нужно хранить состояние игры. Ты сам говорил, хранить 2 снапшота.
Snusmumriken
Конечно
Inellok
И один я изменяю(пока приходят пакеты инпута от игроков), а другой - нет? Зачем тогда другой? Чтобы откат производить?
Snusmumriken
Снапшотики. Если какие-то сообщения приходят с запозданием, ты такой пихаешь их в середину списка (где им место), откатываешь до прошлого снапшота и повторяешь все действия всех игроков между этими снапшотами (и пришедшее сверху), проматывая по чуть-чуть время и обновляя все объекты на разницу между прошлым действием и следующим, и так до последнего. Изи.
Snusmumriken
Тут действительно не самая простая концепция дискретизации непрерывности времени и действий, но это просто.
Inellok
Суть в том, что я отправляю игру в прошлое на такое маленькое время, что это незаметно?
Snusmumriken
Пофигу на какое время, хоть на десять секунд. Просто пересчитывать изменения за десять секунд долго ))
Snusmumriken
И клиенты не получат своей синхронизации, могут быть проблемы при расхождениях данных на клиентах и сервере и рывки при интерполяции.
Snusmumriken
И кстати, если клиент может узнать свою дельту, разве сервер не может узнать дельты для каждого клиента, отправляя им данные с как бы их временем? ))
А вот и статистика по пингу для каждого, и джиттер не только входящего но и исходящего.
Inellok
сервер главнее
Inellok
Snusmumriken
сервер главнее
Это тебе так кажется, клиентам очень не хочется наблюдать тормоза, поэтому желательно высылать с дельтой для них )
Inellok
Inellok
То с дельтой их точно не должно быть
Snusmumriken
Смотри. Ты высылаешь клиентам снапшот и меткой времени с дельтой для данного конкретного клиента. Клиент видит: снапшот создан пол секунды назад (сервер высылает клиенту с дельтой для этого клиента, которую он сам получал). И сверху ещё присыпали кучкой сообщений с действиями игроков. Он такой берёт СВОЁ игровое состояние, интерполирует его до состояния снапшота от сервера, выполняет действия игроков со времени создания снапшота и получает то что надо нарисовать.
Inellok
ужас
Inellok
Я думал, он никакие действия не выполняет
Inellok
Кроме отрисовки и отправки инпута
Snusmumriken
Ха
Snusmumriken
Снапшот был сделан пол секунды назад и передавался в три приёма. Ты хочешь чтобы клиент рисовал то что заведомо устарело?
Inellok
Пол секунды назад... За это время пришёл бы новый
Snusmumriken
Оно и так разумеется устарело, но лучше передавать менее устаревшее, и заодно действия игроков с этого момента, чтобы клиенту было что воспроизводить например.
Inellok
Просто в данном случае мы облегчим задачу серверу, перенеся часть ответственности на клиента
Snusmumriken
На клиенте нет никакой ответственности.
Inellok
просто другая форма записи игрового состояния...
Snusmumriken
Он отправляет только инпут. Но РИСУЕТ более сложно, потому что время движется, чел, а лаги-рывки-тормоза никому не нужны.
Snusmumriken
И клиент точно так же принимает пересланный от сервера чужой инпут, чтобы воспроизводить анимашки.
Если ты будешь передавать только снапшоты, между снапшотами как бы не происходит никаких действий, не на что запускать анимации, все челы такие стоят стоймя и летят пули.
Inellok
Всё так сложна... Я думал проще.
Inellok
Хотя я чекал чужие проектики, и оно по простой схеме всё равно нормально работает без этих супер-примочек
Snusmumriken
"работает", да. Пока всё в пределах локалки без вайфая,
Inellok
Snusmumriken
А теперь вот тебе разница между клиентом и сервером. Принципиально они ничем не отличаются, кстати. Оба держат снапшоты, оба узнают время друг друга, оба имеют очередь действий с временнЫми метками.
Только сервер пересылает действия и снапшоты игроков всем другим игрокам, а клиент высылает действия, ну плюс клиент интерполирует и рендерит. Вот и всё.
Snusmumriken
Так вот. Принципиально ничего сложного в этом нет.
Но да, это не: client:send(my_position, my_vector)
server:set(received_position, received_vector)
Mad
Я пишу асинхронный скрипт на луа, который должен читать fifo файлы. Из-за того что функция их чтения бесконечно ожидает, что в них кто-то передаст данные, когда все остальные функции заканчиваются - скрипт не заканчивается, а все еще ждет содерживое в fifo. Можни ли как-то прибить этот процесс во время выхода, или как это по-другому решается?
Snusmumriken
Может быть, у тебя где-то висит в бесконечном цикле фолдер-вотчер который ловит новые файлы появляющиеся в папке? Типа, на каждой итерации цикла твоей асинхронности создаёт ивент "посмотреть в директорию на предмет новых файлов чтобы добавить их в очередь"? Опять таки, пока ты не скажешь чем пользуешься, проблема неизвестна.
Mad
while true do
fifo_file = io.open("ars", "r")
content = fifo_file:read("*all")
fifo_file:close()
return content
end
Это полная функция, то бишь как-только в fifo поступает инфа процесс запускается по новой. Про асинхронность - я имею ввиду что другие части скрипта выполняются парраллельно, и когда заканчиваются - должны заканчивать и весь скрипт, но ожидание fifo info не дает
Mad
Snusmumriken
Mad
То есть у тебя где-то висит постоянно перезапускаемый процесс, выполняющий этот код?
Я вырезал все моменты за которые мне стыдно, но которые 100% не имеют тут значения, так что процесс заканчивается после изменения переменной, только вот когда скрипт оканчивается и переменная изменяется, какбы должен выполняться последний "выстрел" этого процесса, и заканчивается скрипт только когда ты снова что-то направишь в этот fifo
Mad
Snusmumriken
Попробуй скинуть весь код на pastebin.com. Убери там личное.
Потому что я в твоём примере уже вижу бесполезный цикл, так как
function foo()
while true do
fifo_file = io.open("ars", "r")
content = fifo_file:read("*all")
fifo_file:close()
return content
end
end
При вызове всегда будет выполнять тело цикла и тут же из него выходить, идентично
function foo()
fifo_file = io.open("ars", "r")
content = fifo_file:read("*all")
fifo_file:close()
return content
end
И если загнать её в отдельный процесс а ля
os.execute("start lua scriptwiththatloop.lua") будет то же самое.
Mad
Snusmumriken
Ретурн. Он у тебя безусловный и всегда выводит из текущей функции сразу, вне зависимости от наличия циклов вокруг.
Mad
Mad
Snusmumriken
Так что должна быть фигня постоянно перезапускающая этот как бы цикл.
Mad
Весь код - две функции
function foo()
fifo_file = io.open("ars", "r")
content = fifo_file:read("*all")
fifo_file:close()
return content
end
function bar()
while true do
print(foo())
end
end
И так или иначе - есть while
Mad
Snusmumriken
А вот тут уже цикл должен быть допустим не while true do ... а допустим while event_queue:isNotEmpty() do ... end. Влепи проверку на наличие параллельных задач.
Snusmumriken
А первоначальный mp.command это уже что-то ))
Mad
Mad
Mad
Snusmumriken
Так, вот я открываю доку по mpv.
Snusmumriken
Так. А теперь глобальный такой вопрос: это скрипт для расширения функционала mpv, так?
Mad
Snusmumriken
Допустим, ты сохраняешь в фиксированном месте файлик с плейлистом например, и в момент его появления, mpv должен его подцепить и воспроизвести.
Snusmumriken
Если так то всё очень просто.
timer = mp.add_periodic_timer(1, function()
print("called every second")
fifo_file = io.open("ars", "r")
content = fifo_file:read("*all")
if content then
mp.command(content)
end
fifo_file:close()
end)
Snusmumriken
Используй имеющийся функционал. Тут есть таймеры например.
Snusmumriken
Бесконечный цикл, который ты хочешь использовать — будет парализовать в любом случае. Тем более без пауз он ещё и будет жутко грузить цпу и диск.
Функции с таймерами же куда более эффективны для твоей задачи. И они будут корректно прерываться с завершением работы плеера.
Mad
Не было там ссылки...
Mad
Вау, ничего не работает.
Ок, признаюсь, сейчас покажу полный, настоящий код. Не скинул его сразу, потому-что он показался жутким говнокодом, но видимо у луа так принято :)
--function fifo()
-- print("ars")
-- fifo_file = io.open("ars", "r")
-- content = fifo_file:read("*all")
-- fifo_file:close()
-- return content
--end
--function stop()
-- timer:kill()
-- print("qwf")
-- os.exit()
--end
--function do_fifo()
-- while true do
-- mp.command(fifo())
-- end
--end
-- timer = mp.add_periodic_timer(0, do_fifo)
--mp.register_event("shutdown", stop)
Snusmumriken
Блин, а я сижу и восстанавливаю ))
Mad
Snusmumriken
Да, всякие io.open могут восприниматься как ссылка. Ну сам видишь.
Snusmumriken
Snusmumriken
Это раз. Два — цикл с таймаутом в 0 это жесть. Выставь хотя бы 0.001
Mad
Snusmumriken
function fifo()
print("ars")
fifo_file = io.open("ars", "r")
content = fifo_file:read("*all")
fifo_file:close()
return content
end
timer = mp.add_periodic_timer(0.001, fifo)
mp.register_event("shutdown", function() timer:kill() end)
Всё. Цикл твой не нужен, у тебя за цикл — периодический таймер.
Snusmumriken
Упорно пихая while ты добиваешься парализации ))