Сейчас сколачиваю опалубку под фундамент - т.е. перед фича-фризом навсегда.
Есть вещи, которые абсолютно невозможно добавить *потом*. Надо закладывать прямо в фундамент - как бы тебя самого не раздражали необходимые для этого ахритектурные выверты.
Вот пишешь после битвы что-нибудь остроумное в чат, типа "Какие же вы, синие, лохи нубские! Лол бгг ez". И тут - Хоба! Карта сменилась, всё, что ты писал от всей глубины души - потёрлось нафик, лохи нубские даже прочитать не успели
Такштааа... Игровой мир - не корневая сущность, миров - как минимум два: лобби - отдельно, карта - отдельно. И грузятся они раздельно, и лобби продолжает жить при смене карты, и игрока не выкидывает с сервера при десинке карты, а отправляет на респавн в лобби.
Но. Механизм лагокомпенсации уже продуман для мелочей, поддержка уже внедрена в основы СУБД (включая менеджер памяти инстансов, приученный дропать все объекты протухающего слоя одним тычком, без вызова деструкторов, на чистом CleanupInstance:
- Код: Выделить всё
procedure TChepersyMemoryManager.DeallocAllInstancesInLayer(idx: TCpsLayerIndex);
var
chunk : TChepersyMemoryManagerChunk;
i: integer;
begin
if idx = 0 then Die(MI_ERROR_PROGRAMMER_NO_BAKA, ['Trying to deallocate the base layer is something special, all right.']);
Assert(idx in Cps.LayerIdxUsage, 'Attempt to deallocate layer idx=' + IntToStr(idx) + ' that is not in use');
i:= High(LayerChunks[idx]);
repeat
if i >= High(LayerChunks[idx]) then begin
chunk:= LayerChunks[idx][i];
if Assigned(chunk)
then chunk.DeallocAllInstances;
end;
Dec(i);
until i < 0;
end;
procedure TChepersyMemoryManagerChunk.DeallocAllInstances;
var
p: pointer;
i, j, i1, i2, j1, j2, k, amh: integer;
begin
if f_AllocCount = 0 then Exit;
i1:= f_IdxLow div (8 * sizeof(pointer));
j1:= f_IdxLow mod (8 * sizeof(pointer));
i2:= f_IdxHigh div (8 * sizeof(pointer));
j2:= (8 * sizeof(pointer)) - 1;
for i:= i1 to i2 do begin
if f_AllocMask[i] <> 0 then begin
if i = i2 then j2:= f_IdxHigh mod (8 * sizeof(pointer));
for j:= j1 to j2 do begin
k:= j + (i * sizeof(pointer));
if k > f_IdxHigh then break;
if (f_AllocMask[i] or (ptruint(1) shl j)) = 0 then continue;
p:= pointer(Self) + ptruint(k * f_Size);
TChepersyObject(p).CleanupInstance; // frees arrays and such
end;
end;
j1:= 0;
end;
) и места для *ещё* четырёх слоёв лагокомпенсации тупо нет. Ибо пространство ускоренных полей - страшно ограниченное (32), а они и так отъели от него 8. И ещё 3 из 32 флагов.
Как результат - приходится изощряться.
"Текущий тик" базового слоя должен быть независимым - не свойство лагокомпенсатора, а свойство каждого мира в отдельности. Почему? Потому что мир после закачки снапшота должен догнать настоящее - а это, в худшем случае, до минут.
Глубинный всплывающий тоже должен уметь прыгать через горящие кольца: для разных миров он может всплывать с разной глубины (например, мы компенсируем краткий дисконнект, до 15 секунд, передачей инпутов за это время и быстрой прокруткой вперёд). А ещё локальные лаги и фризы должны выравниваться без последствий, даже если заставляют базовый слой просесть, отстав от границы лагокомпенсации.
В общем, вырисовывается весьма изощрённая картина жонглирования слоями. Назвал лагокомпенсатор TOnion - чувствую, ещё наплачусь с его отладкой.
sts писал(а):а "они" сделали много этажность уровней дума?
Дык три-де полы - одна из первых фич, которую привинтили создатели source port'ов. У лайн-спешиала 160 (задать триде-пол сектору) даже есть опции совместимости для поддержки совсем древних первобытных форматов этого, которые изначально работали совсем по другому.
Но нет, тут речь не про них, а про порталы. Которые в Зандронуме, увы, могут быть только визуальными. Вот GZDoom - там да, с лёгкостью можно соединять комнаты порталами, с лёгкостью многоэтажное здание сделав. В Зандронуме - только трюками, хаками и извращениями.
Alex2013 писал(а):Бо это уже "не дум" будет.
Ну, ты ещё на раздвижные двери бочку покати
Добавлено спустя 12 часов 45 минут 18 секунд:Иронично, сам мир не является расслаиваемым. Расслаиваемыми являются объекты игрового мира, которые он содержит - но не сам мир.
Мир является потомком такой хрени, как список будильников по тикам (узкоспециализированный разрежённый массив). А каждый будильник - это гипердина (массив, сверх-оптимизированный на изменение размера, Push() и Pop()) ссылок на объекты игрового мира, которые надо разбудить.
Рассматриваю заманчивую архитектуру, где мир является полным агностиком своего содержимого и конкретных реализаций - все игровые объекты содержатся в будильниках. А все физические коллайдеры - релятивичны. Т.е. они имеют ссылку на чанк физического пространства, в котором сидят, а тот - в зависимости от конкретной реализации, ссылки на соседние чанки и родительское подпространство. Но в общем случае не существует даже понятия глобальных координат - если объект хочет узнать расстояние и вектор на другой - оба просят родительские чанки искать вверх по структуре (которая может быть какой угодной, в т.ч. пространством, завязанным в неевклидов узел через порталы) пока оба этих поиска не встретятся рукопожатно. То же для проверок видимости (которые, строго говоря, должны быть подпиской на событие поиска, которое может вернуть результат N тиков спустя) и для широковещательных сообщений от игрока "монстры, увидьте меня".
Что-то такое в уме витало, но окончательно вдохновила меня Гиперболика
https://store.steampowered.com/app/1256230/Hyperbolica/ - единственная, насколько знаю, игра, где действие происходит в неевклидовом пространстве, где в полный круг укладываются пять прямых углов (а в карманном измерении фермы, где надо глушить кротов - три прямых угла).
Для "огромного открытого мира" (который, по сути, всегда лишь холст для картины геймплея) у меня давно была идея планеты, сгенерированной субдивижном икосаэдра, где чанки - треугольные... Но никаких коррекций по высоте нет, все чанки - столбики равномерной толщины от верха (нелетабельный космос) до низа (некопабельная магма). Иии... По факту, поверхность планеты - неевклидова плоскость, замкнутая ненатуральным образом, а вся физика - нагло пользуется фактом, что ось вверх - всегда строго вверх. И, тем не менее, никто не мешает совершить кругосветку.
Добавлено спустя 11 часов 20 минут 47 секунд:Мечта была красивой, но нереализуемой. Список будильников по тикам - *разрежённый* массив, элементы могут добавляться по требованию... Например, слоями, отличными от базового... Потом базовый слой полезет в будильник за тот же тик - и... Не выходит у Данилы-мастера каменный цветок.
Ну, отпочковывание нового слоя - будет более дорогой операцией, чем абсолютно бесплатная, похоже. Ибо список будильников тоже надо клонировать, а у него под капотом - в том числе, специализация TMap.