This is a mobile optimized page that loads fast, if you want to load the real page, click this text.

Вопрос Сохранение данных о персонаже во время выхода из игры.

askjbdaksd

Новый участник
10 Май 2022
8
1
22
Всем привет, появился вопрос для разработчиков которые используют mongodb (mongoose).

У меня есть две таблицы: User, Character.
В таблице User я использую ref для сохранения данных о персонаже (в таблице Character), всё это выглядит примерно так:

JavaScript:
import { Schema } from 'mongoose';

const userSchema = new Schema({
    // ....
    character: {
      type: Schema.Types.ObjectId,
      ref: "Character",
    },
// ....
});

В таблице Character у меня есть "position", представленный как объект (для сохранения позиции игрока при его выходе из игры).

Так вот, это всё я веду к тому, что при использовании ивента "playerQuit', я встречаю подобную ошибку: "Expired multiplayer object has been used".
Вот как это выглядит (код):

JavaScript:
playerQuit: async (player: PlayerMp) => {
        try {
         // findUser работает
          const findUser = await UserModel.findOneAndUpdate(
            { serial: player.serial },
            { $set: { loggedIn: false } }
          );

         // Error: Expired multiplayer object has been used (пробовал добавить await, но не помогло)
          UserModel.findOne({ serial: player.serial })
            .populate({ path: "character" }).exec(function (err: any, users: any) {
              if (err) return console.error(`Populate error - ${err}`);
              users.character.position = player.position;
            });
          findUser!.save();
        } catch (e) {
          console.log(e);
        }
},

Просмотрел документацию mongoose, но ничего полезного не нашёл, может плохо искал.
Заранее спасибо!
 

Inoi

/dev/null
Команда форума
Moderator
VIP
15 Окт 2020
3,803
1,859
208
35
а причём здесь вообще монго?
не оч выкупаю как её документация тут может помочь

это же ошибка, которая пишет тебе, что ты пытаешься обращаться к объекту, которого нет

не уверен что правильно сформулирую мысль, но

это разве не происходит из-за асинхронного метода?
для ио кода - игрок уже не в пуле - и просто отдаёт тебе андефайнед, насколько я понимаю
наверное, можно сделать проверку с mp.players.exists(player), ну чисто чтобы убедиться

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

п.с.
примерно нихуя не понимаю в жсе, но как будто бы дело просто в логике
 
Последнее редактирование:

X-Clusiv

Модератор
Команда форума
Moderator
BackEnd developer
4 Окт 2020
708
319
161
30

Inoi

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

JavaScript:
playerQuit: async (player: PlayerMp) => {
    try {
        const dataPlayer = {
            serial: player.serial,
            position: player.position.clone()
        }
        const findUser = await UserModel.findOneAndUpdate(
            { serial: dataPlayer.serial },
            { $set: { loggedIn: false } }
        );

        UserModel.findOne({ serial: dataPlayer.serial })
            .populate({ path: "character" }).exec(function (err: any, users: any) {
            if (err) return console.error(`Populate error - ${err}`);
              users.character.position = dataPlayer.position;
            });
        findUser!.save();
    } catch (e) {
        console.log(e);
    }
},
Как-то так...
 

askjbdaksd

Новый участник
10 Май 2022
8
1
22
Хорошо, сегодня попробую, спасибо за мысль.