PDA

Просмотр полной версии : [Вопрос] Оптимизация



execution
14.06.2019, 19:47
Например, количество домов: 3140 штук. Когда встаёшь на пикап, идёт перебор в 3140 итераций на какой именно ты встал. Можно ли как-то сократить количество итераций? Создавать для каждого итератор и добавлять/удалять дома при входе/выходе зоны стрима мне кажется не очень идея.

DeimoS
15.06.2019, 06:14
Использовать динамические зоны стримера. А стример, в свою очередь, делит всю карту на квадраты и проверяет только те динамические зоны, которые находятся в том же квадрате, в котором находится игрок, либо в ближайших (ну ещё сортирует координатыи т.п., но это уже не суть).
Так же можно заюзать w_points (https://forum.sa-mp.com/showthread.php?t=286009), если по какой-то неизвестной причине ты решил не использовать стример.

Хотя тут проще завязать всё на стандартных пикапах. То бишь, игрок встал на пикап => произошёл вызов OnPlayerPickUpPickup => вызвали нужную ячейку массива, высчитав её из ID пикапа. Если пикапы домов создавать только при старте сервера, то для поиска нужной ячейки не потребуется никаких циклов. Достаточно при создании первого пикапа дома записать ID пикапа в какую-то переменную, а дальше значение этой переменной отнимать от ID пикапа. Если полученное значение не меньше 0 и не больше максимального индекса массива домов - вызван пикап дома.

Daniel_Cortez
15.06.2019, 07:54
Или можно создавать пикапы с помощью стримера, после чего в каждый из них с помощью функции Streamer_SetIntData записать в поле E_STREAMER_EXTRA_ID (либо, если это поле уже под что-то занято - в любое другое поле, не используемое для пикапов; например в E_STREAMER_COLOR или E_STREAMER_HEALTH) ID соответствующего дома. Так из каждого пикапа можно будет с помощью Streamer_GetIntData узнавать ID нужного дома и, как бонус, отодвинуть ограничение по количеству пикапов.

execution
15.06.2019, 10:43
Использовать динамические зоны стримера. А стример, в свою очередь, делит всю карту на квадраты и проверяет только те динамические зоны, которые находятся в том же квадрате, в котором находится игрок, либо в ближайших (ну ещё сортирует координатыи т.п., но это уже не суть).
Так же можно заюзать w_points (https://forum.sa-mp.com/showthread.php?t=286009), если по какой-то неизвестной причине ты решил не использовать стример.

Хотя тут проще завязать всё на стандартных пикапах. То бишь, игрок встал на пикап => произошёл вызов OnPlayerPickUpPickup => вызвали нужную ячейку массива, высчитав её из ID пикапа. Если пикапы домов создавать только при старте сервера, то для поиска нужной ячейки не потребуется никаких циклов. Достаточно при создании первого пикапа дома записать ID пикапа в какую-то переменную, а дальше значение этой переменной отнимать от ID пикапа. Если полученное значение не меньше 0 и не больше максимального индекса массива домов - вызван пикап дома.

Создавать 3140 динамических зон не слишком затратно ли будет? Да, использую динамические пикапы, к сожалению пикапы меняют свой тип при покупки/продажи и не получится использовать последний способ. Спасибо за совет :thank_you:

Daniel_Cortez
15.06.2019, 10:56
Да, использую динамические пикапы, к сожалению пикапы меняют свой тип при покупки/продажи и не получится использовать последний способ.
Так а в чём проблема при пересоздании пикапа заново записать в него ID дома?

execution
15.06.2019, 10:59
Или можно создавать пикапы с помощью стримера, после чего в каждый из них с помощью функции Streamer_SetIntData записать в поле E_STREAMER_EXTRA_ID (либо, если это поле уже под что-то занято - в любое другое поле, не используемое для пикапов; например в E_STREAMER_COLOR или E_STREAMER_HEALTH) ID соответствующего дома. Так из каждого пикапа можно будет с помощью Streamer_GetIntData узнавать ID нужного дома и, как бонус, отодвинуть ограничение по количеству пикапов.

Спасибо за совет, очень помогли.

Ещё вопросик: При удалении данного пикапа, нужно в ручную удалять значение через Streamer_RemoveArrayData или они автоматически удалятся?

- - - Добавлено - - -


Так а в чём проблема при пересоздании пикапа заново записать в него ID дома?

Поздно увидел ваш ответ.

Не знал об данной функции.

DeimoS
15.06.2019, 11:17
Создавать 3140 динамических зон не слишком затратно ли будет?

Нет. Хотя лучше воспользоваться любым другим из вариантов, связанным с пикапами. Если не планируется создавать/удалять дома во время работы сервера, то я бы лучше воспользовался вариантом, который предложил я (записывать ID первого пикапа домов при создании и потом отнимать от ID пикапа, который будет выводить OnPlayerPickUpDynamicPickup). Кода будет меньше (соответственно, проще будет его поддерживать) и отнять значение одной переменной от другой - всяко быстрее, чем вызывать функцию плагина. А если понадобиться создать/удалить дома, достаточно просто будет сделать рестарт сервера.
Для этого достаточно просто сделать функцию, в которую помещать вызов всего кода, который так или иначе создаёт пикапы (загрузку домов и т.п.). Далее просто вызвать сначала
DestroyAllDynamicPickups();
а потом ту функцию, по новой загрузив все данные и пересоздав все пикапы.

Либо же написать отдельно функцию, которая не будет трогать никакую информацию из систем, кроме информации о пикапах. То бишь, функция будет выгружать из базы только координаты пикапов и сразу же их создавать, просто обновляя информацию о пикапах. И это, опять же, только если бы требовалось часто удалять/создавать дома. Но я не думаю, что тебе оно потребуется. Гораздо проще просто в таких ситуациях делать рестарт.

Но и вариант, предложенный Daniel_Cortez, тоже имеет место быть. Всё зависит от того, что тебе потребуется.


При удалении данного пикапа, нужно в ручную удалять значение через Streamer_RemoveArrayData или они автоматически удалятся?

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

execution
15.06.2019, 12:34
Если не планируется создавать/удалять дома во время работы сервера, то я бы лучше воспользовался вариантом, который предложил я (записывать ID первого пикапа домов при создании и потом отнимать от ID пикапа, который будет выводить OnPlayerPickUpDynamicPickup). Кода будет меньше (соответственно, проще будет его поддерживать) и отнять значение одной переменной от другой - всяко быстрее, чем вызывать функцию плагина. А если понадобиться создать/удалить дома, достаточно просто будет сделать рестарт сервера.

Наверное не так поняли меня. Я не могу воспользоваться вашим вариантом не потому, что я создаю дома или их удаляю из игры. А, например, при загрузке я создаю пикап для входа и для выхода в дом. Когда игрок покупает - необходимо изменить модель пикапа для входа. Поэтому придётся удалить пикап и заново его создать с нужной моделью. Если игрок меняет интерьер своего дома, соответственно координаты пикапа выхода меняются и тут так-же само необходимо удалить пикап и создать на нужных координатах.

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

DeimoS
15.06.2019, 12:48
Когда игрок покупает - необходимо изменить модель пикапа для входа. Поэтому придётся удалить пикап и заново его создать с нужной моделью.

Модель пикапа заменяется через всё ту же функцию Streamer_SetIntData. Вот так:
Streamer_SetIntData(STREAMER_TYPE_PICKUP, pickupid, E_STREAMER_MODEL_ID, /*Тут ID модели пикапа*/);



Если игрок меняет интерьер своего дома, соответственно координаты пикапа выхода меняются и тут так-же само необходимо удалить пикап и создать на нужных координатах.
Вообще гораздо логичнее создать один пикап для интерьера на все виртуальные миры (указать "-1" в качестве вирт.мира или же указать конкретные виртуальные миры, создав пикап через CreateDynamicPickupEx), а не плодить 3140 пикапов для разных виртуальных миров.
Но даже в этом случае можно всё так же воспользоваться функциями изменения данных о пикапе. В данном случае - Streamer_SetFloatData.
Менять уже вот эти параметры:
E_STREAMER_X,
E_STREAMER_Y,
E_STREAMER_Z,
E_STREAMER_R_X,
E_STREAMER_R_Y,
E_STREAMER_R_Z,

Может быть такое, что игрок не увидит изменений, пока не подвигается. Это исправляется вызовом функции
Streamer_Update(playerid, STREAMER_TYPE_PICKUP);


Вообще советую получше изучить функционал стримера :) Это далеко не только "волшебный плагин, который как-то позволяет создавать много объектов/пикапов/etc...". Можно начать вот с этой статьи (http://pro-pawn.ru/showthread.php?15934-%D0%94%D0%BE%D0%BF%D0%BE%D0%BB%D0%BD%D0%B8%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D1%8B%D0%B5-%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B8-%D1%81%D1%82%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D0%B0-%D0%A4%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B8-%D0%BC%D0%B0%D0%BD%D0%B8%D0%BF%D1%83%D0%BB%D1%8F%D1%86%D0%B8%D0%B8-%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D0%BC%D0%B8-%D0%A7%D0%B0%D1%81%D1%82%D1%8C-1). А потом перейти на официальный форум, найдя там тему, в которой опубликован стример + почитать описание функций на GitHub.
Умелая работа с функционалом стримера может сильно упростить жизнь и помочь оптимизировать код.

execution
15.06.2019, 14:17
Вообще гораздо логичнее создать один пикап для интерьера на все виртуальные миры (указать "-1" в качестве вирт.мира или же указать конкретные виртуальные миры, создав пикап через CreateDynamicPickupEx), а не плодить 3140 пикапов для разных виртуальных миров.
Тогда я не совсем понимаю как мне нужно будет отследить на какой пикап я встал, дабы получить ид дома. Ведь в этом случае не сработает вариант с отниманием от ид пикапа на который встал - ид 0 созданного для дома, и не сработает вариант от ДК

DeimoS
15.06.2019, 14:58
Тогда я не совсем понимаю как мне нужно будет отследить на какой пикап я встал, дабы получить ид дома. Ведь в этом случае не сработает вариант с отниманием от ид пикапа на который встал - ид 0 созданного для дома, и не сработает вариант от ДК

Смотри.

В начало мода:
new FirstHousePickupID;

При загрузке домов:
for(new i; i < rows; i++)
{
//Выгружаешь данные из кэша MySQL в массив

// Создаёшь пикап входа в дом (тот, что на улице)
hInfo[i][hPickup] = CreateDynamicPickup(...)//Создаёшь пикап
}
FirstHousePickupID = hInfo[0][hPickup];// Запоминаешь ID первого пикапа

public OnPlayerPickUpDynamicPickup(...)
{
if(0 <= pickupid-FirstHousePickupID < sizeof(hInfo))
{
new house_id = pickupid-FirstHousePickupID;
// И дальшейшее действие при входе в дом.
// Например, если хочешь сделать вход по кнопке, то записываешь значение "house_id" в глобальный массив и запускаешь таймер, например, на несколько секунд.
// При срабатывании таймера обнуляешь переменную. А в OnPlayerKeyStateChange смотришь, равна ли переменная какому-либо из ID домов и если равна - делаешь действие входа в дом.
}
}
Получится так: если, допустим, первый ID пикапа дома - 10, то когда игрок будет вставать на пикап с ID 10, мы, вычтя записанный ID, получим 0 - индекс ячейки, в которой записана информация о доме. Это касаемо входа.



Касаемо интерьеров - после цикла загрузки домов запускаешь цикл с количеством итераций, равным количеству интерьеров.
for(new i; i < MAX_HOUSE_INTERIOR; i++)
{
/*переменная =*/ CreateDynamicPickup(/*модель*/, /*тип*/, /*Координаты*/, -1, /*ID интерьера*/); // То бишь, у тебя пикап будет во всех виртуальных мирах, но в конкретном интерьере
}

При входе в дом указываешь виртуальный мир, равный, например:
SetPlayerVirtualWorld(playerid, house_id+1000);

Теперь когда игрок встаёт на пикап интерьера (который выше создали), получаешь текущий виртуальный мир игрока и отнимаешь ту самую 1000. В итоге у тебя получается ID дома, в котором игрок находится на данный момент.

execution
15.06.2019, 19:39
Смотри.

В начало мода:
new FirstHousePickupID;

При загрузке домов:
for(new i; i < rows; i++)
{
//Выгружаешь данные из кэша MySQL в массив

// Создаёшь пикап входа в дом (тот, что на улице)
hInfo[i][hPickup] = CreateDynamicPickup(...)//Создаёшь пикап
}
FirstHousePickupID = hInfo[0][hPickup];// Запоминаешь ID первого пикапа

public OnPlayerPickUpDynamicPickup(...)
{
if(0 <= pickupid-FirstHousePickupID < sizeof(hInfo))
{
new house_id = pickupid-FirstHousePickupID;
// И дальшейшее действие при входе в дом.
// Например, если хочешь сделать вход по кнопке, то записываешь значение "house_id" в глобальный массив и запускаешь таймер, например, на несколько секунд.
// При срабатывании таймера обнуляешь переменную. А в OnPlayerKeyStateChange смотришь, равна ли переменная какому-либо из ID домов и если равна - делаешь действие входа в дом.
}
}
Получится так: если, допустим, первый ID пикапа дома - 10, то когда игрок будет вставать на пикап с ID 10, мы, вычтя записанный ID, получим 0 - индекс ячейки, в которой записана информация о доме. Это касаемо входа.

Это я понял, затруднения были с пикапами выхода. Уяснил, спасибо за помощь

Daniel_Cortez
16.06.2019, 06:11
Нет. Хотя лучше воспользоваться любым другим из вариантов, связанным с пикапами. Если не планируется создавать/удалять дома во время работы сервера, то я бы лучше воспользовался вариантом, который предложил я (записывать ID первого пикапа домов при создании и потом отнимать от ID пикапа, который будет выводить OnPlayerPickUpDynamicPickup). Кода будет меньше (соответственно, проще будет его поддерживать) и отнять значение одной переменной от другой - всяко быстрее, чем вызывать функцию плагина. А если понадобиться создать/удалить дома, достаточно просто будет сделать рестарт сервера.
Вообще полагаться на распределение ID пикапов - такая себе затея, на самом деле.

Во-первых, что, если в новых версиях SA-MP (хотя, кого я обманываю? В Open.MP!) ID пикапов будут распределяться, как у таймеров (т.е. когда один и тот же ID никогда не используется для нового объекта дважды)?
Пока что единственное, что может помешать такому изменению, это то, что крупные серверы тоже могут полагаться на распределение пикапов, но и это не гарантия. Когда для одних типов объектов ID распределяются по одному принципу, для других - по другому, для третьих - по третьему, ИМХО, вполне логично, что рано или поздно в Open.MP захотят привести их к одному унифицированному принципу.

Во-вторых, что, если до пересоздания был удалён пикап с меньшим ID? Новый пикап займёт тот самый меньший ID и сопоставление с ним ID дома будет некорректным.
Конечно, можно сделать так, чтобы другие системы мода не удаляли пикапы или чтобы пикапы для домов создавались первыми, но это будет дополнительным требованием ко всем остальным системам мода. Это будет побочный эффект. И это не нормально.



Модель пикапа заменяется через всё ту же функцию Streamer_SetIntData. Вот так:
Streamer_SetIntData(STREAMER_TYPE_PICKUP, pickupid, E_STREAMER_MODEL_ID, /*Тут ID модели пикапа*/);
Нет, не заменяется. Игроки, которые при такой "смене" модели уже былы в зоне стрима (например, при той же покупке/продаже), будут видеть прежнюю модель. Новую модель увидят только те игроки, которые потом войдут в зону стрима пикапа.

DeimoS
16.06.2019, 10:12
Вообще полагаться на распределение ID пикапов - такая себе затея, на самом деле.

Во-первых, что, если в новых версиях SA-MP (хотя, кого я обманываю? В Open.MP!) ID пикапов будут распределяться, как у таймеров (т.е. когда один и тот же ID никогда не используется для нового объекта дважды)?
Пока что единственное, что может помешать такому изменению, это то, что крупные серверы тоже могут полагаться на распределение пикапов, но и это не гарантия. Когда для одних типов объектов ID распределяются по одному принципу, для других - по другому, для третьих - по третьему, ИМХО, вполне логично, что рано или поздно в Open.MP захотят привести их к одному унифицированному принципу.

Во-вторых, что, если до пересоздания был удалён пикап с меньшим ID? Новый пикап займёт тот самый меньший ID и сопоставление с ним ID дома будет некорректным.
Конечно, можно сделать так, чтобы другие системы мода не удаляли пикапы или чтобы пикапы для домов создавались первыми, но это будет дополнительным требованием ко всем остальным системам мода. Это будет побочный эффект. И это не нормально.

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

Касаемо второго пункта - так я же и написал, что если вдруг понадобится создать/удалить дом, то после этого можно удалить ВСЕ пикапы с сервера и пересоздать их по новой. Либо сделать рестарт, что проще и надёжнее. Дома редко удаляют/изменяют после того, как в первый раз их расставили. Так что вряд ли вообще автора коснётся эта "проблема". Я написал о ней лишь для предупреждения и пояснения того, что все изменения следует планировать заранее, ибо они могут поломать систему.

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


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


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

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

Daniel_Cortez
17.06.2019, 12:16
Касаемо второго пункта - так я же и написал, что если вдруг понадобится создать/удалить дом, то после этого можно удалить ВСЕ пикапы с сервера и пересоздать их по новой. Либо сделать рестарт, что проще и надёжнее.
Что опять же будет побочным эффектом, сказывающимся на работе других систем. Из таких эффектов и складывается код, "прибитый гвоздями", который нельзя просто так изменить, не сломав или ещё как-то повлияв на другие системы мода - собственно, от этого я и хотел бы предостеречь автора темы.


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


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


Во-первых, увидят, ибо стример сразу обновляет изменённые таким образом данные (по крайней мере модель - точно, ибо сам пользовался в одном из заказов недавно этим).
Во-вторых, даже если бы не обновлял, то я писал о "Streamer_Update", которая исправила бы ситуацию.
Так может у тебя в том заказе и был вызов Streamer_Update() сразу после изменения свойств объекта? Иначе это недокументированная возможность, ибо в репо плагина (https://github.com/samp-incognito/samp-streamer-plugin/wiki/Natives-%28Data-Manipulation%29) написано, что функции Streamer_Set*Data() только изменяют ассоциированные с объектом данные; про то, что они форсят обновление объекта - ни слова.

DeimoS
17.06.2019, 15:45
Что опять же будет побочным эффектом, сказывающимся на работе других систем. Из таких эффектов и складывается код, "прибитый гвоздями", который нельзя просто так изменить, не сломав или ещё как-то повлияв на другие системы мода - собственно, от этого я и хотел бы предостеречь автора темы.

Эмм, перечитай ещё раз мои и свои ответы. Я указал автору темы на то, что в случае добавления/удаления домов потребуется делать рестарт, а так же расписал как всё сделать без рестарта. В варианте без рестарта я указал то, что нужно будет заново удалять и создавать вообще все пикапы, указав на функцию, которая сделает это. Ты же написал о возможном баге, который случился бы в случае, если удалять и создавать только пикапы домов, на что я тебе ответил, что такого бага не будет, ибо я говорил про удаление всех пикапов.

Вариант с редактированием домов без рестарта я написал в качестве простого примера, который показывает, что проблему можно решить разными путями + уточнив, что на практике гораздо практичнее и проще будет делать рестарт. А позже придумал ещё один вариант с "резервированием" пикапов, дабы не париться с удалением. Всё это - по сути, исправление несуществующей проблемы, которая появляется только если пытаться возвести ситуацию в абсолют. По факту, как я уже несколько раз замечал, система домов - это система, в которой изменения бывают крайне редки. Поэтому нет нужды придумывать какие-то дополнительные извращения ради удаления/создания домов. Достаточно делать все изменения перед рестартом (а сервер без рестартов всё равно долго работать не может) и всё.

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


Так может у тебя в том заказе и был вызов Streamer_Update() сразу после изменения свойств объекта?

Нет.

UPD: Даже перепроверил сейчас специально всё. Вот код, которым проверял
new gPickupid;
CMD:gotopickup(playerid, params[])
{
gPickupid = CreateDynamicPickup(19056, 23, 1456.8945, -1744.4506, 13.5469, 0, 0);
SetPlayerPos(playerid, 1456.8945, -1744.4506, 13.5469);
return 1;
}

CMD:setpickup(playerid, params[])
{
Streamer_SetIntData(STREAMER_TYPE_PICKUP, gPickupid, E_STREAMER_MODEL_ID, strval(params));
SendClientMessage(playerid, -1, "set");
return 1;
}

CMD:updatepickup(playerid, params[])
{
Streamer_Update(playerid, STREAMER_TYPE_PICKUP);
SendClientMessage(playerid, -1, "update");
return 1;
}
Модель пикапа обновляется сразу после изменения.


Иначе это недокументированная возможность, ибо в репо плагина (https://github.com/samp-incognito/samp-streamer-plugin/wiki/Natives-%28Data-Manipulation%29) написано, что функции Streamer_Set*Data() только изменяют ассоциированные с объектом данные; про то, что они форсят обновление объекта - ни слова.

Ну вообще, по моему, это вполне ожидаемый принцип работы функции, ведь в стримере есть только информация об объектах/пикапах и т.п., а значит любые изменения подразумевают то, что ты хочешь изменить всё вышеперечисленное, а не просто сохранить какую-то инфу. Это как, например, в описании функции "format" не пишут того, что функция может переписать данные, а не добавлять их к тем, что уже есть в массиве... Пример, конечно, такой себе, но суть, надеюсь, ясна.
Ну и возможность обновлять всё перечисленное вручную как-то не особо находит применения в моей фантазии: только проблемы с тем, что одни игроки будут видеть одну инфу, а другие - другую.