nezuo / lapis

A DataStore abstraction library for Roblox
https://nezuo.github.io/lapis/
MIT License
55 stars 10 forks source link

attempt to index nil with 'GetUserIds' #36

Closed jisham318 closed 7 months ago

jisham318 commented 7 months ago
Failed to load profile for IraTenebrarum (#11211818): -- Promise.Error(ExecutionError) --

The Promise at:

ReplicatedStorage.rbxts_include.node_modules.@rbxts.lapis.out.lapis.Collection:99 function load
ServerScriptService.TS.services.save-data-service:98 function onPlayerAdded
ServerScriptService.TS.services.save-data-service:83

...Rejected because it was chained to the following Promise, which encountered an error:

ReplicatedStorage.rbxts_include.node_modules.@rbxts.lapis.out.lapis.Collection:92: attempt to index nil with 'GetUserIds'
ReplicatedStorage.rbxts_include.node_modules.@rbxts.lapis.out.lapis.Collection:92
ReplicatedStorage.rbxts_include.node_modules.@rbxts.lapis.out.Promise:172 function runExecutor
ReplicatedStorage.rbxts_include.node_modules.@rbxts.lapis.out.Promise:181

Promise created at:

ReplicatedStorage.rbxts_include.node_modules.@rbxts.lapis.out.lapis.Collection:87 function load
ServerScriptService.TS.services.save-data-service:98 function onPlayerAdded
ServerScriptService.TS.services.save-data-service:83

here's where everything is being called:

private collection: Collection<DataStoreSaveType>;
    private documents: Map<Player, Document<DataStoreSaveType>> = new Map();
    private playerTroves: Map<Player, Trove> = new Map();

    constructor() {
        setConfig({
            saveAttempts: 5,
            loadAttempts: 20,
            loadRetryDelay: 1,
            showRetryWarnings: true,
            dataStoreService: DataStoreWrapper,
        });
        this.collection = createCollection(IS_STAGING ? "STAGING" : "PRODUCTION", {
            defaultData: serializeSave(defaultPlayerSave),
            validate: (data: DataStoreSaveType) => {
                print(data, deserializeSave(data));
                return true;
            },
        } as CollectionOptions<DataStoreSaveType>);
    }

    public onStart(): void {
        Players.PlayerAdded.Connect((player) => this.onPlayerAdded(player));
        Players.PlayerRemoving.Connect((player) => this.onPlayerRemoving(player));
    }

    private onPlayerAdded(player: Player): void {
        if (this.documents.has(player)) {
            player.Kick("Player already has a document loaded on this server");
            return;
        }
        this.collection
            .load(`Player${player.UserId}`)
            .then((document) => {
                if (!player.IsDescendantOf(game)) {
                    document.close().catch((err) => warn(err));
                    return;
                }
                //document.addUserId(player.UserId); // I thought this was the culprit
                const playerTrove = new Trove();
                store.setPlayerSave(player.UserId, deserializeSave(document.read()));
                playerTrove.add(
                    store.subscribe(selectPlayerSave(player.UserId), (playerSave: PlayerSave | undefined) => {
                        if (!playerSave) return;
                        document.write(serializeSave(playerSave));
                    }),
                );
                playerTrove.add(() => {
                    if (this.documents.has(player)) {
                        this.documents.get(player)!.close();
                        this.documents.delete(player);
                    }
                });
                this.documents.set(player, document);
                this.playerTroves.set(player, playerTrove);
            })
            .catch((err) => {
                warn(`Failed to load profile for ${player.Name} (#${player.UserId}): ${err}`);
                player.Kick("Failed to load save file, please check back later.");
            });
    }
nezuo commented 7 months ago

It looks like you are using some sort of DataStore wrapper. Whatever you are using needs to support new DataStore APIs like DataStoreKeyInfo:GetUserIds(). If the wrapper you are using is just a mock, you can use mine which supports these APIs: https://github.com/nezuo/data-store-service-mock

jisham318 commented 7 months ago

This is the wrapper I'm using: https://github.com/VernandoGames/MockDataStoreService/tree/main/src I'm writing this game in roblox-ts, and using this wrapper because it has typings for typescript and is published to npm. I really need this to work offline in studio. Any pointers?

nezuo commented 7 months ago

There's not much I can do to help. It would require some manual effort but you can fork my project and add typescript typings. I looked at the link you sent and the typings are very simple (a couple of lines) and you could use that same approach.

jisham318 commented 7 months ago

Closing, unrelated to this repo. For anyone else who needs this fixed, the @rbxts/mockdatastoreservice (VernandoGames/MockDataStoreService) package doesn't have an implementation for GetRequestBudgetForRequestType because it's based on an older version of buildthomas/MockDataStoreService. Can be resolved by copying the type definitions from the first repo into a fork of the second.