Перейти к контенту

Рекомендуемые сообщения

[q]Условия возникновения: имея кучу всяких данных в таблице, которые хотелось бы сохранить, перевожу таблицу в строку.[/q]

 

Кстати, а зачем ?

Ссылка на комментарий

@Dennis_Chikin, просто у @Zander_driver'а  некорректно построенна фраза.

Вероятно данные в исходной таблице имели структуру вложенных таблиц. Объем данных в таблице таков, что в сумме превышает (или может) ~8 кБ ,

и поэтому исходная таблица по-элементно переводилась в строки... (каждая субтаблица в свою строку), чтобы запоминать по частям.

"Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени

Ссылка на комментарий

@Artos, а разве хранилище само не конвертирует таблицы в строки и обратно для "удобства пользования" ?

P.S. Не изучал пока...

Ссылка на комментарий

По большому счету, даже выделенное хранилище совсем не нужно как таковое, со своим собственным API.

Имеет смысл воткнуть его непосредственно в save_all/load_all. Все равно они вызываются исключительно при сохранениях/загрузках, но зато - всегда. А тем более не нужны постоянные бессмысленные конвертации таблиц в строки и обратно при передаче между функциями - в любом случае передается ссылка.

Это просто-напросто трата памяти и времени.

 

И даже при загрузке/сохранении получается опять же то же самое двойное/тройное преобразование, которое ведет лишь к разбуханию сохраняемых данных.

Итого, всего лишь добавить к оригинальным float, bool, строка и объект еще один тип - таблица.

 

ergo, прямо там и отслеживать размер пакета, и при необходимости начинать новый, что с таблицей - на много проще, чем с длинной строкой.

 

P.S. А в соли мы вообще занимались полной ерундой, сохраняя мнимую "совместимость" сэйвов, когда все равно по куче других причин каждое дополнение == новая игра. И, кстати, меня слегка уже поддостало даже в той же соли выковыривать отовсюду кучу заведомо бессмысленных переменных, и еще более бессмысленных "конвертаций". В нетпакете у актора там хранить реально почти нечего.

Ссылка на комментарий

@sapsan, скрипт хранилища позволяет сохранять и табличные типы данных (и др.), но(!) если кол-во (кило)байт после перевода таблици в строку (и даже с компрессией) превысит 8 кБ - то скрипт не будет автоматом разрезать эту таблицу на куски, а ругнется в лог и пропустит эту таблицу.

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

 

"Удобства использования" все же имеют границы, за пределами которых начинаются неудобства.  :crazy:  Вот тут и нужно вспоминать про оптимизацию... и выбирать критерии.

"Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени

Ссылка на комментарий

"Удобства использования" все же имеют границы, за пределами которых начинаются неудобства.

Тоесть обычное преобразование таблицы в строку и обратно выходит за границы удобств ?
Ссылка на комментарий

@Dennis_Chikin, что-то ты брякнул, что и мне сложновато понять...  :crazy:

Во-первых, скрипт хранилища как раз и выполняет все "непосредственно в save_all/load_all".

Во-вторых, полностью согласен, что в пакете актора по сути то хранить можно "копейки", но как раз в рассматриваемом случае потребно целую "кучу" где-то, но сохранять.


@sapsan, тебе же уже не раз написано, что исходная таблица в данном случае содержит такое кол-во данных, что при переводе в строку (сериализации) кол-во байт строки превышает 8 кБ. А это уже не просто "удобства", а ограничение движка игры!

Т.о. если хочешь использовать "удобное хранение" - потрудись не превышать размер строки в 8 кБ или же сохраняй/дроби сам как тебе вздумается.

 

Если же все твои данные таковы, что ни при каких условиях каждая "порция" для сохранения не превысит ограничения по пакету - пользуйся сколь угодно преобразованиями.

Изменено пользователем Artos

"Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени

Ссылка на комментарий

простейшая модификация оригинала:

function pstor_save_tbl( t, pk )
	pk:w_u8( pstor_table )
	local p
	for k, v in pairs( t ) do
		if type( k ) == "number" then pk:w_u8( pstor_number ); pk:w_float( k )
		else pk:w_u8( pstor_string ); pk:w_stringZ( k )
		end
		if v == true then pk:w_u8( pstor_true )
		elseif v == false then pk:w_u8( pstor_false )
		else
			p = type( v )
			if p == "number" then pk:w_u8( pstor_number ); pk:w_float( v )
			elseif p == "string" then pk:w_u8( pstor_string ); pk:w_stringZ( v )
			elseif p == "userdata" then
				pk:w_u8( pstor_custom )
				if v.classname == k then pk:w_stringZ( "" )
				else pk:w_stringZ( v.classname )
				end
				v:save( pk )
			elseif p == "table" then pstor_save_tbl( v, pk )
			else abort( "pstor_save_all, not registered type: %s, k: %s", p, k )
	end	end	end
	pk:w_u8( pstor_end_t )	
end


function pstor_save_all( npc, pk )
	local pstor = db.storage[npc:id()].pstor
	if not pstor then
		pstor = {}
		db.storage[npc:id()].pstor = pstor
	end
	local n = 0
	for k, v in pairs( pstor ) do n = n + 1 end
	pk:w_u32( n )
	local p
	for k, v in pairs( pstor ) do
		pk:w_stringZ( k )
		if v == true then pk:w_u8( pstor_true )
		elseif v == false then pk:w_u8( pstor_false )
		else
			p = type( v )
			if p == "number" then pk:w_u8( pstor_number ); pk:w_float( v )
			elseif p == "string" then pk:w_u8( pstor_string ); pk:w_stringZ( v )
			elseif p == "userdata" then
				pk:w_u8( pstor_custom )
				if v.classname == k then pk:w_stringZ( "" )
				else pk:w_stringZ( v.classname )
				end
				v:save( pk )
			elseif p == "table" then pstor_save_tbl( v, pk )
			else abort( "pstor_save_all, not registered type: %s, k: %s", t, k, _util.to_str( npc ) )
	end	end	end
end

 

 

Загрузка - аналогично. Дальнейшая модификация путем скрещивания с "универсальным хранилищем" для толстых таблиц - очевидна. Осталось придумать, для чего бы могли понадобиться эти толстые таблицы.

  • Нравится 1
Ссылка на комментарий

@Dennis_Chikin, это проще, чем писать менеджер сохранения таблицы в виде простых типов.


тебе же уже не раз написано, что исходная таблица в данном случае содержит такое кол-во данных, что при переводе в строку (сериализации) кол-во байт строки превышает 8 кБ

Где это написано ? От автора вопроса уточнения не было. И его сообщение я трактую однозначно - он сохраняет много преобразованных в строки таблиц, а не одну огромную таблицу с подтаблицами. Было лишь твоё предположение о последнем варианте. И если оно верно - это проблема автора вопроса, а не баг в хранилище. Если же не верно - вероятно он замучил хранилище до выявления бага. Почему бы не подождать уточнения от него самого, а не тыкать друг в друга авторитетными гипотезами ?
 

простейшая модификация оригинала

:good2:



Оставляю вас далее строить свои домысли и погадалки...

И ушел он в обнимку со своим домыслом... :crazy:

Изменено пользователем sapsan
  • Нравится 1
  • Не нравится 1
Ссылка на комментарий

@Dennis_Chikin, ты "тихо сам с собою" иль как?  :crazy:

Исходное сообщение Zander_driver о том, что при сохранении большой таблицы у него со скриптом se_stor.script возникает ошибка переполнения.

Способы конвертирования таблицы в строку (иль иной тип данных) давным давно известны, применяются и в данном случае не рассматриваются (пока).

Ты спросил: "Зачем переводить в строку", на что дан ответ: "Чтобы разрезать таблицу на части, т.к. строка всей таблицы превышает допустимый размер!".

Ну и что же ты с чем собрался скрещивать, предлагая очередной (с ошибками и сильно ограниченный) вариант сериализации "аля xStream" при тех же самых 8-ми кило на пакет?!   :crazy:

 

 

 

Где это написано ?

Автор исходного сообщения пишет об одной таблице, мною (в ответ на заданный вопрос о переводе в строки) дано пояснение (единственно возможное в данной ситуации)...

Оставляю вас далее строить свои домысли и погадалки... Вот только что и кому вы пытаетесь показать иль объяснить?  :wub:

 

P.S. Вот только троллить, переходя на личности, не стОит... Теперь просто вас начну игнорировать.

Изменено пользователем Artos

"Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени

Ссылка на комментарий

В наличии есть матрица углов поворота объекта и его позиция. Могу из неё также получить углы Эйлера.
Никто случаем не может показать готовую функцию (можно даже не на Lua, лишь бы понятная была) с помощью которой зная эти данные можно получить направляющий вектор?
(в смысле вектор, который при сложении с позицией показывает на точку в метре от объекта, на которую он смотрит - грубо говоря то что возвращает direction() у объекта или device().cam_dir у камеры)
 
Необходимо получить дирекцию кости, но я могу только углы Эйлера\матрицу поворота из неё вытащить. А как через них получить направляющий вектор (он кстати вроде по другому называется) я честно говоря не знаю. 


UPD: Вроде выкрутился вот такой шнягой:
 

local ph_shell = self.object:get_physics_shell()
local ph_element = ph_shell:get_element_by_bone_name("link")
 

function extract_direction(ph_element)
local m = ph_element:global_transform()
local p,b,h = extract_euler_xzy(m)
return vector():setHP(h, p)
end
 

extract_euler_xzy - http://pastebin.com/6ijsymZ4

Изменено пользователем *Shoker*
  • Нравится 1

Можно просто Shoker, форум АМК съел моё старое имя и не хочет отдавать о_О

Мастер аномалий на свою заднюю точку.

Ссылка на комментарий

Неужели я неясно выразился. Нет же, Артос, никогда там не было одной большой таблицы, тем более размером более 8кб. были тысячи таблиц примерно по 200 байт. Чтобы не перекладывать на se_stor то с чем я и сам справлюсь, упаковал их в строки самостоятельно. и стал записывать. ни одна из строк не превышала 130 байт, просто их были тысячи. и при размере пакета 8000 байт возникало переполнение. сделал запас в 200 байт - проблема исчезла. лог, если так уж необходим, могу воспроизвести, вернув обратно на 8000. Полагаю ошибка где то в алгоритме "когда надо переключаться на следующий объект". т.к. повторюсь, ни один из элементов которые я скармливал в se_stor, никогда не был такого размера чтобы в одиночку вызвать переполнение.

Ну и по поводу сохранения

тысяч элементов... я думаю из того вопроса который был в личке, вы поймете что я сохраняю. Отсюда уже несложно сообразить зачем.

 

  • Нравится 1

Мод, где не бывает одинаковых путей - Судьба Зоны. (Лучшее, что у меня получилось на X-Ray) На базе модифицированного движка OGSR Engine.

Бывший мододел на X-Ray / Начинающий игродел на Unreal Engine. Программист.

AMD Ryzen 9 7950X (16 ядер, 5.7ГГц); RTX 3080; 128 ГБ DDR5; Arctic Liquid Freezer II-420; 3 ТБ SSD PCIe 4.0; 4ТБ HDD.

Ссылка на комментарий
Неужели я неясно выразился.

Как можно видеть из возникших вопросов - недостаточно ясно..., а точнее для любителей шарад или гаданий.

@Zander_driver, какова цель твоего исходного поста #5414?

Сообщить о возможной ситуации, когда в скрипте (неизвестном для многих) у тебя возникает ошибка? А кому, кроме тебя иль меня это интересно? Да и для меня, без технической информации, это просто пустой оффтопик, а тебе ".. было лень  :) поэтому просто уменьшил предельный размер пакета..".

Даже на мой ответ и фразу о необходимости хотя бы лога(!), ты продолжаешь пустые предполагалки и "если так уж необходим, могу воспроизвести,...".

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

 

Ну а по оптимизации, не стОит из меня делать Кашпировского... Я все же не экстрасенс и не любитель гадать на кофейной гуще, чтобы по куцым и завуалированным фразам в личке строить догадки и тем более соображать зачем это кому-то.

Ну а пока мне все же непонятны такие "тысячи записей из строк" - остаюсь прежнего мнения о  не оптимальности  принятых для сохранения данных. Что-то не верится, что эти несколько тысяч записей возникают в следствии игры и именно эксклюзивны, а не воспроизводимы вновь. (ну да это как говорится: "хозяин барин")

 

 

 

Полагаю ошибка где то в алгоритме "когда надо переключаться на следующий объект".

Хм, судя по описаниям, ошибка НЕ в алгоритме, а в конкретном числе для границы пакета. Если это так, то я бы предпочел перепроверить и определить причину, чтобы установить безопасную границу, а не гадать в слепую...

 

P.S. Кстати, ты так и не ответил на заданный вопрос:

[q]Условия возникновения: имея кучу всяких данных в таблице, которые хотелось бы сохранить, перевожу таблицу в строку.[/q] Кстати, а зачем ?

 

 

...

и, просто предположение, не из-за "ручного" ли перевода возникает проблема?

Изменено пользователем Artos
  • Не нравится 1

"Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени

Ссылка на комментарий

Artos,
Про ошибки хочу подробностей. Ну, кроме как про выкинуть остатки "псевдосовместимости" в виде подсчета количества переменных, которые низачем не нужны, но знатно тормозят.
По поводу ограниченности - это еще всякую лабуду типа векторов сохранять ? Не, не нужна. Их все равно надо чуть не при каждой операции руками копировать, и при этом черт его знает, что у них там внутри.

А модифицируется это в дальнейшем, если бы оно было зачем-то надо, просто тупо проверкой размера нетпакета после записи очередной переменной, и если больше максимально разрешенного размера - создаем другое хранилище, и продолжаем писать уже в него.

Теперь возвращаемся к преобразованию таблиц в строки:
С учетом того, что в луа для этого нет адекватных средств - оверхэд получается просто чудовищный. Сами данные при этом также разбухают (ага, тэги, да и просто num в strZ).
Далее, получив строку, не лезущую в остаток пакета, я так понимаю, предлагается применить к ней string.sub(), в обрамлении некоторой логики ? Опять же, оверхэд. В то время, как при поэлементной записи делить ничего не надо - просто продолжать писать в другой. И так же и читать.

Да, записаны данные получаются "рыхло". Сэйв увеличивается в размере. Но поскольку это происходит уже не в скрипте - это будет всяко быстрее.

Zander_driver, а добавить контроль размера пакета после записи каждой строки, и писать его в лог - не ? Естественно, что при записи в него 8 кил - переполнится.

Изменено пользователем ColR_iT
Ссылка на комментарий

 

 

Про ошибки хочу подробностей.

Хотеть не вредно, но лучше их попросить...  :crazy:

После того как посмотрел топик по разработкам в солянке, стал понятен твой интерес к этой теме. Ошибки бывают (и у тебя присутствуют) различного типа:

1. Ошибка применения необъявленной переменной: в строке 

else abort( "pstor_save_all, not registered type: %s, k: %s", t, k, _util.to_str( npc ) ) 

используется необъявленная переменная (t вместо p), что приведет к потере информации в функции прерывания игры о причине предыдущей ошибки.

2. Ошибочно предлагать "простейшую модификацию оригинала" для использования типа данных "userdata" при том, что не оговоривается обязательность наличия в таких данных неких v.classname и v:save, коих в оригинальных объектах в игре практически не встречается или имеются только в классах типа биндеров. 

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

3. Можно и далее продолжить разбор "простейшей модификации", но не вижу пока надобности, т.к. имеются более продвинутые варианты записи различных данных в сэйв(ы). Если есть желание сравнить и порассуждать - нет проблем, но тогда тебе придется ознакомиться с уже имеющимися вариантами (хотя бы с тем, о котором речь в исходном посте).

 

 

 

 

А модифицируется это в дальнейшем, если бы оно было зачем-то надо, просто тупо проверкой размера нетпакета после записи очередной переменной, и если больше максимально разрешенного размера - создаем другое хранилище, и продолжаем писать уже в него.
Именно "тупо"! К твоему сведению если ты в нет-пакет что-то записал, то что-то проверять после записи уже поздно будет... т.к. если переполнение, то придется уже "выкидывать" этот нет-пакет и все перезаписывать заново. Именно на этом этапе и пишет про ошибку Zander_driver, и именно тут имеется некая неопределенность: то ли выбранная граница максимума для записи велика, то ли имеется ошибка перевода в строки и их запись в сэйв...

 

По "преобразованию таблиц в строки" нам пока рано (иль поздно) говорить.

1. Моя позиция проста: "Любая таблица для записи в сэйв НЕ должна превышать 8 кБ! Если превышает - модмейкер должен заранее позаботиться о разделении на приемлемые части." Именно на этом основан алгоритм скрипта общего хранилища, т.е. любые строки/таблицы более 8 кБ просто игнорируются с сообщением об этом в лог.

Если  тебе или кому-то хочется на лету делить автоматом строки/таблицы и распределять по разным объектам с последующими слияниями - нет проблем, пишите свои варианты (с string.sub() иль иным).  ;)

2. Варианты сериализации и даже с компрессией давно уже есть и никакого чудовищного оверхеда не наблюдается. Если организовать данные и писать их в сэйв с умом(!) то даже при записи чисел строками можно выиграть в объемах! Но все конечно зависит от контента и огульно все сваливать в кучу - ошибочно!

Кстати, это еще один тип ошибки (не оптимальность) в твоем варианте записи pstor'ов.

 

 

 

 

Но поскольку это происходит уже не в скрипте - это будет всяко быстрее.
Позвольте поинтересоваться: "не в скрипте" - это где? где это будет быстрее и по какой такой причине?  :crazy:

"Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени

Ссылка на комментарий

и, просто предположение, не из-за "ручного" ли перевода возникает проблема?

Помилуйте. Тот пост я писал утром, собираясь на работу. Возпроизводить тот лог у меня банально не было времени. и, по вашему преположению. Я для полноты картины выводил в лог все те строки, которые отправлялись в se_stor на сохранение. ни одна из них не превышала 130 символов.

Сейчас воспроизведу тот вылет...

Мод, где не бывает одинаковых путей - Судьба Зоны. (Лучшее, что у меня получилось на X-Ray) На базе модифицированного движка OGSR Engine.

Бывший мододел на X-Ray / Начинающий игродел на Unreal Engine. Программист.

AMD Ryzen 9 7950X (16 ядер, 5.7ГГц); RTX 3080; 128 ГБ DDR5; Arctic Liquid Freezer II-420; 3 ТБ SSD PCIe 4.0; 4ТБ HDD.

Ссылка на комментарий

@Zander_driver, никто и не гонит и не требует сразу же реагировать на реплики, как и вообще писать посты без необходимой информации. 

Нужны логИ, по строкам которых можно было бы понять причину сбоя/ошибки.

Если по какой-то причине сбой именно из-за "переполнения", то нужен лог записи, в котором были бы указаны объемы записи в каждый элемент и соответственно строки лога чтения из этих элементов из сэйва. В скрипте вывод этой информации предусмотрен.

Так же, нет подозрений на превышение какой-то отдельной строки более чем 8 кБ, а есть подозрение, что или сама строка после "ручного" перевода своей таблички оказалась "странной" или еще какой-то неясный сбой при сохранении цепочки строк (пересечение имен, недопустимые символы в именах, ...)

В общем не гадать нужно, а анализировать информацию (которая отсутствует)!

"Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени

Ссылка на комментарий

Можно ли каким то образом сменить комьюнити смарт-террейна в игре? (ТЧ)

Кстати, пытаясь выяснить этот вопрос, попытался получить список серверных объектов по clsid.smartterrain. С удивлением обнаружил что таких объектов на сервере нет. Хотя в class_registrator.script регистрируется именно такой. И смарт-террейны в игре есть.

сам скрипт рабочий, когда с его помощью получаю серверные объекты сталкеров, мобов, аномалий, оружия и прочего - все работает. И возвращает все что требуется.

Изменено пользователем Zander_driver

Мод, где не бывает одинаковых путей - Судьба Зоны. (Лучшее, что у меня получилось на X-Ray) На базе модифицированного движка OGSR Engine.

Бывший мододел на X-Ray / Начинающий игродел на Unreal Engine. Программист.

AMD Ryzen 9 7950X (16 ядер, 5.7ГГц); RTX 3080; 128 ГБ DDR5; Arctic Liquid Freezer II-420; 3 ТБ SSD PCIe 4.0; 4ТБ HDD.

Ссылка на комментарий

@Zander_driver, все же по-аккуратнее и по-понятнее стОит формулировать вопросы/посты.

1. Нет в оригинальных играх серии Сталкера объектов с сидами 'smartterrain', а есть для 'smart_terrain' (clsid.smart_terrain). Этот же сид регистрируется и в class_registrator.script.

2. Как можно сменить то, чего нет? Нет для смарт-террейнов такого понятия 'комьюнити'. Имеется возможность задать параметр 'accepted_communities' - табличку в которой перечислены допустимые/разрешенные для гулага группировки.

Можно было бы net-пакетами менять в кастомдате значения для этого параметра, но... пока нет стабильных вариантов для этого класса.

Но не сложно в игре в нужное время менять эту табличку (accepted_communities) по своему разумению, естественно дополнительно написав свои изменяющие функции.

Изменено пользователем Artos

"Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени

Ссылка на комментарий

Создайте аккаунт или авторизуйтесь, чтобы оставить комментарий

Комментарии могут оставлять только зарегистрированные пользователи

Создать аккаунт

Зарегистрировать новый аккаунт в нашем сообществе. Это несложно!

Зарегистрировать новый аккаунт

Войти

Есть аккаунт? Войти.

Войти
  • Недавно просматривали   0 пользователей

    Ни один зарегистрированный пользователь не просматривает эту страницу.

AMK-Team.ru

×
×
  • Создать...