• Из-за обновления 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) последний раз были обновлены:

Вопрос Использование сокетов для получения json инвентаря

Vermilion

Специалист
Автор темы
29 Сен 2021
292
145
80
33
Приветствую, не могу найти в чем проблема получения json через сокеты. Возможно кто то посмотрит не замыленым взглядом.

sockets/app.ts
JavaScript:
import express from 'express';
import http from 'http';
import fs from 'fs';
import path from 'path';
import { socketsConfig,socketsConfigInventory } from './config';
import { Server as SocketIoServer, Socket } from 'socket.io';
import { getInventoryData } from '../database'; // Подключаем функцию получения данных инвентаря

const app = express();
const server = http.createServer(app);
const io = new SocketIoServer(server);

const mapHTML = fs.readFileSync(path.join(__dirname, '../../socks/index.html'), 'utf8');
const socketIO = fs.readFileSync(path.join(__dirname, '../../socks/socket.io.js'), 'utf8');
const socketIOMap = fs.readFileSync(path.join(__dirname, '../../socks/socket.io.js.map'), 'utf8');

app.get('/', (req, res) => {
    res.send(mapHTML);
});

app.get('/socket.io.js', (req, res) => {
    res.send(socketIO);
});

app.get('/socket.io.js.map', (req, res) => {
    res.send(socketIOMap);
});

io.on('connection', (socket: Socket) => {
    console.log('Client connected');

    // Обработка запроса данных инвентаря через сокеты
    socket.on('getInventoryData', async () => {
      try {
        const inventoryData = await getInventoryData();
        // Отправка данных инвентаря обратно клиенту через сокеты
        socket.emit('inventoryData', inventoryData);
      } catch (error) {
        console.error('Error fetching inventory data:', error);
        // Обработка ошибки и отправка сообщения об ошибке клиенту через сокеты
        socket.emit('inventoryDataError', 'Internal Server Error');
      }
    });
  });

server.listen(socketsConfig.listenPort);
console.log('[SOCKET]: Socket server is ready');
app.listen(socketsConfigInventory.listenPort);
console.log('[SOCKET]: Socket inventory is ready');

export default server;

ui/src/app.tsx
JavaScript:
import React, { useEffect, useState } from 'react';
import './index.sass';
import rpc from '../../shared/rpc';
import Auth from "./interfaces/Auth";
import Notifications from "./interfaces/Notifications";
import { SOUNDS_LIST } from './utils/audio/list';
import { useAppDispatch } from "./hooks/redux";
import { Howl } from "howler";
import CreateChar from "./interfaces/CreateChar";
import Inventory from './interfaces/Inventory';



// @ts-ignore
window.soundSystem = {
    list: {},
    banList: [],
}

// @ts-ignore
const playSound = ({ file, volume = 0.1, loop = false }) => {
    // @ts-ignore
    const { list } = window.soundSystem;
    const dir = file.split('/')[0];
    const isListHasFile = SOUNDS_LIST.hasOwnProperty(file);
    const isFileLooped = loop && list.hasOwnProperty(file);
    // @ts-ignore
    const isFileBanned = ~window.soundSystem.banList.indexOf(dir);
    if (!isListHasFile || isFileLooped || isFileBanned) return;
    let sound = new Howl({
        // @ts-ignore
        src: [SOUNDS_LIST[file]],
        autoplay: true,
        loop,
        volume,
        onend: () => {
            if(!loop) {
                // @ts-ignore
                this.unload()
            }
        },
    });
    if (!loop) return sound.off();
    list[file] = sound;
};
// @ts-ignore
window.soundSystem.playSound = playSound;

const stopSound = (file: string) => {
    // @ts-ignore
    const { list } = window.soundSystem;
    if (!list.hasOwnProperty(file)) return;
    list[file].unload();
    delete list[file];
};
// @ts-ignore
window.soundSystem.stopSound = stopSound;

// @ts-ignore
Object.keys(SOUNDS_LIST).forEach((file) => window.soundSystem.playSound({ file, volume: 0 }));

const App: React.FC = () => {
    const dispatch = useAppDispatch();
    const [inventory, setInventory] = useState([]);
    const [loading, setLoading] = useState(true);
    const [inventoryOpen, setInventoryOpen] = useState(false);

    const fetchInventoryData = async () => {
      try {
        console.log('Fetching inventory data...');
        const response = await fetch('http://localhost:25006/getInventoryData', {
          method: 'POST', // Обновленный метод
        });
        if (!response.ok) {
          throw new Error('Ошибка загрузки данных инвентаря');
        }

        const inventoryData = await response.json();
        setInventory(inventoryData);
        setLoading(false);
      } catch (error) {
        console.error('Ошибка загрузки данных инвентаря:', error.message);
        setLoading(false);
      }
    };

    const handleKeyPress = (event: KeyboardEvent) => {
      console.log('Key pressed:', event.key);
      if (event.key.toLowerCase() === 'ш') {
        setInventoryOpen(true);
        fetchInventoryData();
      }
    };

    useEffect(() => {
      document.addEventListener('keydown', handleKeyPress);

      return () => {
        document.removeEventListener('keydown', handleKeyPress);
      };
    }, []);

    rpc.register('executeRpc', (action: any) => {
      dispatch(action);
    });

    return (
      <>
        <Notifications />
        <Auth />
        <CreateChar />
        {loading ? (
          <p>Загрузка данных инвентаря...</p>
        ) : (
          <Inventory inventory={inventory} isOpen={inventoryOpen} />
        )}
      </>
    );
  };

  export default App;

ui/scr/interfaces/Inventory/index.tsx
JavaScript:
import React, { useState } from 'react';
import './styles.sass';

interface InventoryProps {
    inventory: any[];
    isOpen: boolean;
  }

  const Inventory: React.FC<InventoryProps> = ({ inventory, isOpen }) => {
    //document.body.innerHTML = `Key pressed: ${isOpen}`;
    return (
      <div style={{ display: isOpen ? 'block' : 'none' }}>
        <div id="inventory">
          {inventory.map((item) => (
            <div key={item.itemName} className="inventory-slot">
              {item.itemName}
            </div>
          ))}
        </div>
      </div>
    );
  };

  export default Inventory;

server/modules/database/inventoryRouters.ts
JavaScript:
import express, { Request, Response } from 'express';
import { Inventory } from '../database/Models/Inventory';
const inventoryRouter = express.Router();
inventoryRouter.all('/getInventoryData', async (req: Request, res: Response) => {
  try {
    const inventoryData = await Inventory.findAll();
    res.json(inventoryData);
  } catch (error) {
    console.error('Ошибка при получении данных инвентаря:', error);
    res.status(500).json({ error: 'Внутренняя ошибка сервера' });
  }
});


Таблица в БД существует. При открытии http://localhost:25006/getInventoryData получаю Cannot GET /getInventoryData
 
Последнее редактирование модератором:

Jerry (ChatGPT)

AI-powered language model
VIP
helper
17 Окт 2023
862
1,158
5
Привет! Проблема возникает потому что в файле ui/src/app.tsx вы используете метод POST при отправке запроса на URL /getInventoryData, а в файле server/modules/database/inventoryRouters.ts вы определили маршрут для этого URL с помощью метода all, который обрабатывает любые методы запроса.

Для решения проблемы, вам нужно изменить метод запроса в файле ui/src/app.tsx на GET:

JavaScript:
const fetchInventoryData = async () => {
  try {
    console.log('Fetching inventory data...');
    const response = await fetch('http://localhost:25006/getInventoryData', {
      method: 'GET',
    });
    // ...
  } catch (error) {
    console.error('Ошибка загрузки данных инвентаря:', error.message);
    setLoading(false);
  }
};

После этого, когда вы откроете URL http://localhost:25006/getInventoryData, вы должны получить данные инвентаря без ошибок.
 

Vermilion

Специалист
Автор темы
29 Сен 2021
292
145
80
33
Еще варианты?
 

Vermilion

Специалист
Автор темы
29 Сен 2021
292
145
80
33
Возможно, кто то посоветует иные способы получения информации из БД? В приоритете вопрос производительности без прямых запросов к базе данных (безопасность)
 

XDeveluxe

Модератор
Команда форума
high coder
30 Авг 2021
2,220
1,425
191
27
Обычный вариант пересылки json инвентаря на клиент и с клиента на CEF уже не катит?
Это же проект в RAGE, а не AAA игра за миллионы долларов.

Хочу заметить, что поднимать тему разрешено не чаще, чем 1 раз в 24 часа.
С момента создания темы 24 часа не прошло.
 

Vermilion

Специалист
Автор темы
29 Сен 2021
292
145
80
33
Обычный вариант пересылки json инвентаря на клиент и с клиента на CEF уже не катит?
Это же проект в RAGE, а не AAA игра за миллионы долларов.

Хочу заметить, что поднимать тему разрешено не чаще, чем 1 раз в 24 часа.
С момента создания темы 24 часа не прошло.
Сначала ты в каких то моментах делаешь на тяп-ляп, а потом твой проект превращается в очередную редагу
 

XDeveluxe

Модератор
Команда форума
high coder
30 Авг 2021
2,220
1,425
191
27
Сначала ты в каких то моментах делаешь на тяп-ляп, а потом твой проект превращается в очередную редагу
О боже.
"Очередная редага" построена лучше, чем 90% того, что я видел связанного с модами на этом форуме.
Один вякает про редагу, стадо кивает. Нет, я рад, что есть те, кто хотя бы пытается сделать что-то своими руками, но по-моему Вы пытаетесь изобрести велосипед, тем самым только усложняете себе разработку и взаимодействие с данными в будущем, не говоря уже о безопасности. Заддосят твой сокет, получать данные станет невозможно - твой мод встанет?
 
  • Like
Реакции: wholinc

wholinc

Специалист
24 Янв 2023
775
454
95
23
Сначала ты в каких то моментах делаешь на тяп-ляп, а потом твой проект превращается в очередную редагу
Не думаю, что это тянет на "тяп-ляп", да и редага не плохая сборка. Просто школьники навредили репутации.
 

Vermilion

Специалист
Автор темы
29 Сен 2021
292
145
80
33
Я по этому и спросил про альтернативные варианты, которые на повредят безопасности
 

Andrew Fares

Специалист
7 Окт 2020
69
41
79
Я по этому и спросил про альтернативные варианты, которые на повредят безопасности
Я слабо шарю за JS на бэке, но вот мне режет глаз момент с

Код:
const inventoryRouter = express.Router();
inventoryRouter.all('/getInventoryData', async (req: Request, res: Response) => {

Разве не надо принимать путь через inventoryRouter.get(... ?
 

Andrew Fares

Специалист
7 Окт 2020
69
41
79
А вообще... стоит ли делать отдельный iframe для инвентаря? Я что-то подобное реализовывал и возникает много НО.
Проще держать всё в рейджовском CEF и будет как минимум плюс в одной локали для клиентской части рейджа и CEF, а в твоём случае тебе придётся прокидывать либо напрямую в iframe что-то, либо через сервер в твой брокер>сокет
 
  • Like
Реакции: Inoi и Vermilion

Andrew Fares

Специалист
7 Окт 2020
69
41
79
@Vermilion ты хоть отпиши, помогло или нет. Если помогло, то тему закрыть
 

MoonFusion

Гуру
high coder
14 Июн 2021
308
249
123
Я по этому и спросил про альтернативные варианты, которые на повредят безопасности
В некоторых моментах я солидарен с @xDeveluxe, например с фразой "не стоит придумывать велосипед", сокеты в LSJ были имплементированы лишь для оптимизации ивентов, но не как отдельный способ организации ивентов.

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

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

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

XDeveluxe

Модератор
Команда форума
high coder
30 Авг 2021
2,220
1,425
191
27
По поводу редаги, мем конечно, все что угодно построено лучше чем редага, её используют лишь потому, что она работает и это полноценный готовый мод, но все же это не меняет того факта что реализована она отвратительно, в особенности архитектурно.
Всё что угодно это что?
Почему все говорят "всё что угодно", но не показывают ни 1 реального показателя того, что лучше? Я бы реально с радостью посмотрел на эти чудо произведения и их хвалёную архитектуру, а позже послушал "почему у них не получилось", в то время как у "редаги" получилось.
Мем - это хейт, который под собой ничем не подкреплён. Да, написан он не Senior разработчиками с 25 летним стажем, но:
1) Это работало на большую аудиторию и работает.
2) Для проекта в RAGE и не нужна архитектура уровня Google.

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

MoonFusion

Гуру
high coder
14 Июн 2021
308
249
123
Всё что угодно это что?
Почему все говорят "всё что угодно", но не показывают ни 1 реального показателя того, что лучше? Я бы реально с радостью посмотрел на эти чудо произведения и их хвалёную архитектуру, а позже послушал "почему у них не получилось", в то время как у "редаги" получилось.
Мем - это хейт, который под собой ничем не подкреплён. Да, написан он не Senior разработчиками с 25 летним стажем, но:
1) Это работало на большую аудиторию и работает.
2) Для проекта в RAGE и не нужна архитектура уровня Google.


Подловили - я в душе не ебу про сокеты.
И самое интересное, что могу ещё 10 лет про них ничего не знать, раз они мне никогда не пригождались за столько времени.
Подозреваю что ты не слышал и не видел хороших модов, потому что хорошие моды как правило не сливают в сеть.
Я прекрасно понимаю твоё желание защитить то, чем ты кормишься, и прекрасно понимаю твои аргументы "Это работает" и конечно же "Для рейджа не надо хорошо", но правда в том, что RedAge это пережиток прошлого, пора принять это и двигаться дальше. Я не намерен раздувать эту тему дальше
 

XDeveluxe

Модератор
Команда форума
high coder
30 Авг 2021
2,220
1,425
191
27
Подозреваю что ты не слышал и не видел хороших модов, потому что хорошие моды как правило не сливают в сеть.
:peppe_roller:
Я прекрасно понимаю твоё желание защитить то, чем ты кормишься
Откуда тебе знать чем я кормлюсь?
Никогда не перестану удивляться, как люди говорят за спиной о том, чего не знают - в частности о том, кто чем занимается.
прекрасно понимаю твои аргументы "Это работает" и конечно же "Для рейджа не надо хорошо"
То, что не надо "хорошо" - я не говорил.
Я говорил, что не нужны навыка Senior'а, это большая разница, не находишь?
Не переиначивай слова.

Итого:
Я не знаю ничего про сокеты.
Ты не знаешь ничего ни про меня, ни про то, как работают и устроены крупные проекты.
 
  • Durka
Реакции: MoonFusion

Vermilion

Специалист
Автор темы
29 Сен 2021
292
145
80
33
В некоторых моментах я солидарен с @xDeveluxe, например с фразой "не стоит придумывать велосипед", сокеты в LSJ были имплементированы лишь для оптимизации ивентов, но не как отдельный способ организации ивентов.

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

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

@Vermilion я бы не стал использовать подобную реализацию, это избыточное, будет вполне достаточно стандартных ивентов рейджа для обмена данными.
Спасибо, отказался от использования сокетов для инвентаря. Буду использовть стандартные ивенты
 
  • Like
Реакции: MoonFusion