• Из-за обновления GTA 5 (был добавлен новый патч) может временно не работать вход в RAGE Multiplayer.

    ERROR: Your game version is not supported by RAGE Multiplayer.

    Данная ошибка говорит о том, что GTA V обновилась до новой версии (GTA Online тоже). Вам необходимо обновить саму игру в главном меню вашего приложения (Steam / Epic Games / Rockstar Games).
    Если после этого RAGE:MP все равно не работает - вам нужно дождаться выхода патча для самого мультиплеера (обычно это занимает от нескольких часов до нескольких дней).

    Новости и апдейты Rockstar Games - https://www.rockstargames.com/ru/newswire/
    Статус всех служб для Rockstar Games Launcher и поддерживаемых игр: https://support.rockstargames.com/ru/servicestatus


    Grand Theft Auto 5 (+ GTA Online) последний раз были обновлены:

Вопрос Создание объектов из .xml

Vermilion

Специалист
Автор темы
29 Сен 2021
317
164
80
33
Приветствую. Пытаюсь добавить мапинг на сервер с помощью TS.
С моддингом я сталкиваюсь впервые, по этому есть некоторые вопросы.
Как правильно добавлять объекты, возможно есть более простое решение?

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

Код:
import * as xml2js from 'xml2js';
import fs from 'fs';
import path from 'path';
class Vector3 {
    constructor(public x: number, public y: number, public z: number) {}
}

declare namespace mp {
    export const objects: any;

    // Определение класса Vector3
    export class Vector3 {
        constructor(x: number, y: number, z: number);
    }
}

interface PositionRotation {
    X: [string];
    Y: [string];
    Z: [string];
    Pitch?: [string];
    Roll?: [string];
    Yaw?: [string];
}

interface Placement {
    ModelHash?: string[];
    Type?: string[];
    Dynamic?: string[];
    FrozenPos?: string[];
    HashName?: string[];
    InitialHandle?: string[];
    ObjectProperties?: { TextureVariation: string[] }[];
    OpacityLevel?: string[];
    LodDistance?: string[];
    IsVisible?: string[];
    MaxHealth?: string[];
    Health?: string[];
    HasGravity?: string[];
    IsOnFire?: string[];
    IsInvincible?: string[];
    IsBulletProof?: string[];
    IsCollisionProof?: string[];
    IsExplosionProof?: string[];
    IsFireProof?: string[];
    IsMeleeProof?: string[];
    IsOnlyDamagedByPlayer?: string[];
    PositionRotation?: PositionRotation[];
    Attachment?: { isAttached: string[] }[];
}

interface SpoonerPlacements {
    Note?: string;
    AudioFile?: { volume: string };
    ClearDatabase?: string;
    ClearWorld?: string;
    ClearMarkers?: string;
    IPLsToLoad?: { load_mp_maps: string; load_sp_maps: string };
    IPLsToRemove?: string[];
    WeatherToSet?: string;
    StartTaskSequencesOnLoad?: string;
    ReferenceCoords?: {
        X: string;
        Y: string;
        Z: string;
    };
    Placement?: Placement[] | Placement;
}

async function loadXML(filePath: string): Promise<SpoonerPlacements> {
    const xmlData = fs.readFileSync(filePath, 'utf-8');

    return new Promise((resolve, reject) => {
        xml2js.parseString(xmlData, { explicitArray: false }, (err, result) => {
            if (err) {
                reject(err);
            } else {
                resolve(result as SpoonerPlacements);
            }
        });
    });
}

async function processXML(xmlData: SpoonerPlacements): Promise<mp.objects.Object[] | null> {
    const spoonerPlacements = xmlData as SpoonerPlacements;

    if (!spoonerPlacements || !spoonerPlacements.SpoonerPlacements.Placement) {
        console.error('Неверный формат данных в XML');
        return null;
    }

    const placements = Array.isArray(spoonerPlacements.SpoonerPlacements.Placement)
    ? spoonerPlacements.SpoonerPlacements.Placement
    : [spoonerPlacements.SpoonerPlacements.Placement];

    const createdObjects = await Promise.all(placements.map(async (item: any) => {
        if (item.ModelHash && item.PositionRotation && item.PositionRotation.X && item.PositionRotation.Y && item.PositionRotation.Z && item.PositionRotation.Yaw) {
        const myObjects = mp.objects.new(item.ModelHash, new mp.Vector3(item?.PositionRotation?.X,item?.PositionRotation?.Y,item?.PositionRotation?.Z), {
            rotation: new mp.Vector3(0, 0, item?.PositionRotation?.Yaw),
            alpha: 255,
            dimension: 0,
        });
        return myObjects.id;
        } else {
            console.error('Неверный формат данных для создания объекта:', item);
            return null;
        }
    }));

    return createdObjects;
}

const filePath = path.join(__dirname, 'maps/city.xml');

async function createObj() {
    // Вызов функции загрузки XML и обработки данных
    try {
        const xmlData = await loadXML(filePath);
        const parsedData = await processXML(xmlData);
        console.log(parsedData);
    } catch (error) {
        console.error('Ошибка при обработке XML:', error);
    }
}

createObj();
.xml фаил в формате:
Код:
<Placement>
        <ModelHash>0x376cb307</ModelHash>
        <Type>3</Type>
        <Dynamic>false</Dynamic>
        <FrozenPos>true</FrozenPos>
        <HashName>prop_rub_buswreck_06</HashName>
        <InitialHandle>381954</InitialHandle>
        <ObjectProperties>
            <TextureVariation>0</TextureVariation>
        </ObjectProperties>
        <OpacityLevel>255</OpacityLevel>
        <LodDistance>16960</LodDistance>
        <IsVisible>true</IsVisible>
        <MaxHealth>1000</MaxHealth>
        <Health>0</Health>
        <HasGravity>true</HasGravity>
        <IsOnFire>false</IsOnFire>
        <IsInvincible>false</IsInvincible>
        <IsBulletProof>false</IsBulletProof>
        <IsCollisionProof>false</IsCollisionProof>
        <IsExplosionProof>false</IsExplosionProof>
        <IsFireProof>false</IsFireProof>
        <IsMeleeProof>false</IsMeleeProof>
        <IsOnlyDamagedByPlayer>false</IsOnlyDamagedByPlayer>
        <PositionRotation>
            <X>-184.888977</X>
            <Y>-899.207703</Y>
            <Z>28.4471703</Z>
            <Pitch>3.18055451e-14</Pitch>
            <Roll>-5.41569989e-07</Roll>
            <Yaw>9.24961281</Yaw>
        </PositionRotation>
        <Attachment isAttached="false" />
    </Placement>

Консоль запуска:

Код:
[DONE] "server" package has been loaded.
[INFO] Starting packages...
[DONE] Server packages have been started.
[
   0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11,
  12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
  24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
  36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
  48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
  60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
  72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83,
  84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
  96, 97, 98, 99,
  ... 231 more items
]

Что я делаю не так?
 

Jerry (ChatGPT)

AI-powered language model
VIP
helper
17 Окт 2023
954
1,178
5
Привет! Из вашего кода не совсем ясно, где вы присваиваете созданные объекты переменной mp.objects. У вас есть скрипт mp.objects.new, который создает объекты, но их идентификаторы не сохраняются.

Вы можете попробовать изменить функцию processXML следующим образом:

Код:
async function processXML(xmlData: SpoonerPlacements): Promise<mp.objects.Object[] | null> {
  const spoonerPlacements = xmlData as SpoonerPlacements;

  if (!spoonerPlacements || !spoonerPlacements.SpoonerPlacements.Placement) {
    console.error('Неверный формат данных в XML');
    return null;
  }

  const placements = Array.isArray(spoonerPlacements.SpoonerPlacements.Placement)
    ? spoonerPlacements.SpoonerPlacements.Placement
    : [spoonerPlacements.SpoonerPlacements.Placement];

  const createdObjects: mp.objects.Object[] = [];

  for (const item of placements) {
    if (item.ModelHash && item.PositionRotation && item.PositionRotation.X && item.PositionRotation.Y && item.PositionRotation.Z && item.PositionRotation.Yaw) {
      const myObject = mp.objects.new(item.ModelHash, new mp.Vector3(
        parseFloat(item.PositionRotation.X),
        parseFloat(item.PositionRotation.Y),
        parseFloat(item.PositionRotation.Z)
      ), {
        rotation: new mp.Vector3(0, 0, parseFloat(item.PositionRotation.Yaw)),
        alpha: 255,
        dimension: 0,
      });
      createdObjects.push(myObject);
    } else {
      console.error('Неверный формат данных для создания объекта:', item);
    }
  }

  return createdObjects.length ? createdObjects : null;
}

Теперь созданные объекты сохраняются в переменной createdObjects, и функция возвращает массив созданных объектов.
 

Inoi

/dev/null
VIP
15 Окт 2020
2,456
1,455
208
34
xml можно конвертнуть в ymap и собрать dlc
ну это так чисто к слову
 

Vermilion

Специалист
Автор темы
29 Сен 2021
317
164
80
33
xml можно конвертнуть в ymap и собрать dlc
ну это так чисто к слову
Для каждого созданного объекта я планирую добавлять уникальные параметры для взаимодействия.
На сколько это может ударить по производительности?
 

Inoi

/dev/null
VIP
15 Окт 2020
2,456
1,455
208
34
Для каждого созданного объекта я планирую добавлять уникальные параметры для взаимодействия.
На сколько это может ударить по производительности?
ну это зависит от того как именно будет написано твоё взаимодействие
если например при приближении к каждому - дёргаться сервер, который потом будет для всех клиентов вокруг что-то запускать синхронизированное - возможно слегка будет, особенно если какой-нибудь додик будет подходить-отходить
а так, это ну невозможно точно сказать, всё же зависит от самой реализации а не просто от факта наличия взаимодействий
 

Vermilion

Специалист
Автор темы
29 Сен 2021
317
164
80
33
ну это зависит от того как именно будет написано твоё взаимодействие
если например при приближении к каждому - дёргаться сервер, который потом будет для всех клиентов вокруг что-то запускать синхронизированное - возможно слегка будет, особенно если какой-нибудь додик будет подходить-отходить
а так, это ну невозможно точно сказать, всё же зависит от самой реализации а не просто от факта наличия взаимодействий
Если конвертировать в dlc, то это будут обычные статические объекты карты а не интерактивные. Верно?
 

Inoi

/dev/null
VIP
15 Окт 2020
2,456
1,455
208
34
Если конвертировать в dlc, то это будут обычные статические объекты карты а не интерактивные. Верно?
не очень понимаю что значит статические, а что - интерактивные
 

Voyage Adminov

Активный участник
Мошенник
13 Дек 2023
73
8
30
не очень понимаю что значит статические, а что - интерактивные
Например если заспавнить сгоревшую тачку, то если маппинг на клиенте, то после выезда из зоны стрима тачки и въезда обратно, она заспавнится там, где ее как бы не толкали. А если сделать это на сервере, то все должно быть иначе, и можно сохранять новые позиции
 
  • Like
Реакции: Vermilion

Vermilion

Специалист
Автор темы
29 Сен 2021
317
164
80
33
а, я подумал что речь идёт о новых объектах а не о том что уже есть в жта
а зачем тогда вообще xml?
много объектов сразу экспортировано?
Для более удобного редактирования через Мар Editor. Пока точное количество не могу сказать. Возможно около 1000 по всей карте