Verse persitent data problem

"I’d like to put a leaderboard on my island that shows the player’s name and their total monster eliminations with persistent data that isn’t deleted after every match.

My code registers the player but the data is not persistent, and the scoreboard resets after every match."

This is the actual code

using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/UI }
using { /Verse.org/Simulation/Tags }
using { /UnrealEngine.com/Temporary/SpatialMath }
using { /Verse.org/Native }
using { /Fortnite.com/Characters }
using { /Fortnite.com/Playspaces }
using { /Fortnite.com/Game }
using { /Fortnite.com/Teams }
using { /Verse.org/Random }
using { /Fortnite.com/UI }
using { /Verse.org/Colors }
using { /Verse.org/Assets }
using { /Verse.org/Concurrency }
using { /Fortnite.com/Devices/CreativeAnimation }
using { /Fortnite.com/Devices/CreativeAnimation/InterpolationTypes }

leaderboard_entry := class<final><persistable>:
    PlayerName : string = ""
    Kills : int = 0

monster_leaderboard_device := class(creative_device):
    @editable
    CreatureSpawners : []creature_spawner_device = array{}

    @editable
    DisplayPanel_Blue : billboard_device = billboard_device{}

    @editable
    DisplayPanel_Red : billboard_device = billboard_device{}

    @editable
    var LeaderboardData : []leaderboard_entry = array{}

    MakeLeaderboardMessage<localizes>(Text : string) : message = "{Text}"
    
    # Funzione per ottenere il nome del giocatore come message
    GetPlayerName<localizes>(Agent : agent) : message = "{Agent}"

    OnBegin<override>()<suspends> : void =
        for (Spawner : CreatureSpawners):
            Spawner.EliminatedEvent.Subscribe(OnCreatureEliminated)
        
        LoadLeaderboard()
        UpdateDisplay()

    OnCreatureEliminated(Result : device_ai_interaction_result) : void =
        if (Agent := Result.Source?):
            UpdatePlayerKills(Agent)
            UpdateDisplay()

    UpdatePlayerKills(Agent : agent) : void =
        if (Player := player[Agent]):
            # Ottieni il nome come message e convertilo in string
            PlayerMessage := GetPlayerName(Agent)
            PlayerName := Localize(PlayerMessage)
            var Found : logic = false
            
            for (Index -> Entry : LeaderboardData):
                if (Entry.PlayerName = PlayerName):
                    if (set LeaderboardData[Index] = leaderboard_entry{PlayerName := PlayerName, Kills := Entry.Kills + 1}):
                        set Found = true

            if (Found = false):
                set LeaderboardData += array{leaderboard_entry{PlayerName := PlayerName, Kills := 1}}

            SortLeaderboard()

    SortLeaderboard() : void =
        var SortedData : []leaderboard_entry = array{}
        for (Entry : LeaderboardData):
            var Inserted : logic = false
            for (Index -> SortedEntry : SortedData):
                if (Entry.Kills > SortedEntry.Kills):
                    var NewArray : []leaderboard_entry = array{}
                    if (Index = 0):
                        set NewArray = array{Entry} + SortedData
                    else:
                        if (FirstPart := SortedData.Slice[0, Index]):
                            if (SecondPart := SortedData.Slice[Index, SortedData.Length]):
                                set NewArray = FirstPart + array{Entry} + SecondPart
                    set SortedData = NewArray
                    set Inserted = true
            if (Inserted = false):
                set SortedData += array{Entry}
        
        if (SortedData.Length > 5):
            if (TrimmedData := SortedData.Slice[0, 5]):
                set LeaderboardData = TrimmedData
        else:
            set LeaderboardData = SortedData

    UpdateDisplay() : void =
        var DisplayText : string = "Top 5 Monster Hunters\n"
        for (Index -> Entry : LeaderboardData):
            set DisplayText += "{Index + 1}. {Entry.PlayerName}: {Entry.Kills}\n"
            DisplayPanel_Blue.SetText(MakeLeaderboardMessage(DisplayText))
            DisplayPanel_Red.SetText(MakeLeaderboardMessage(DisplayText))

    LoadLeaderboard() : void =
        if (LeaderboardData.Length = 0):
            set LeaderboardData = array{}

That’s not a thing. Verse can’t actually access a players name. And, AFAIK, verse leaderboard functionality has not been added to UEFN yet.

Hey @gidiodev how are you?

I’ve been testing your code and there are some aspects of persistance that you are not handling. For example, you are not saving or loading any data for the players. You are only adding the score for each kill, but you don’t save that score anywhere.

You will need to add a weak-map to store the data for each player, add functions to save that data every time is needed, add functions to load that data in the “on begin”, etc.

I highly recommend you to watch this series of videos to understand how to handle the persistence!

It explains how to properly setup persistence, how to save data, how to load that data, and how to avoid future issues with the system!

Hope this helps you!

Yes, but that does not change the fact he can’t do what he’s trying to do anyway. You can’t examine or manipulate or save or store a players name in Verse. It’s protected. If you try to treat it like a string it will give you “Anonymous[256]”.

Also, you can’t persist leaderboards like that. There’s no functionality for leaderboards in UEFN. Some form of it, however, is supposed to be added in Q4 2025, I think.

1 Like

Hello @lantram !

Thanks a lot for the clarification! I didn’t consider the possibility of storing the players’ real nicknames!

1 Like