1. The forums will be archived and moved to a read only mode in about 2 weeks (mid march).

What am I doing wrong with managing my MySQL data?

Discussion in 'Development' started by Levi, Feb 11, 2020.

  1. Levi

    Levi Skeleton

    Messages:
    955
    GitHub:
    captainleviftw
    I have this code on PlayerJoinEvent to check if player exists on my database. If the player does exist, store the player's data into an array. If the player is new, create an account for the player. This works fine; however, whenever players join instantaneously, this code just return errors. Errors that seemingly pop up because I am managing my data incorrectly. . How can I prevent that? I was thinking of making some kind of query to manage the data of each players one by one, but i don't know how to do that. I am using libasyql.
    PHP:
    PlayerJoinEvent
    public function accountExists Player $player )
            {
            
                
    $this->connector->executeSelectQueries::GET_ALL, [
                    
    "uuid" => (string)$player->getUniqueId(),
                ], function ( array 
    $rows ) use ( $player ) : void {
                
                    if ( isset( 
    $rows] ) ) {
                        
    $this->getManager()->storePlayerData$player );
                        echo 
    "exists";
                    } else {
                        
    $this->createAccount$player );
                        echo 
    "not exists";
                    }
                } );
            }
    PHP:
    /**
             *
             * Store player's data. This one is really important.
             *
             * @param Player $player
             *
             * @return bool
             */
            
    public function storePlayerData Player $player )
            {
            
                
    $uuid = (string)$player->getUniqueId();
                
    $this->getPlugin()->getMySQLProvider()->loadPlayersData(
                    
    $player,
                    function ( array 
    $data ) use ( $uuid$player ) {
                    
                        foreach (
    $data as $_data) {
                            
    $this->getPlayerData()->player_balance$uuid ] = $_data"BALANCE" ];
    //and many more such as kills, deaths, etc
                        
    }
                    } );
                
    $event = new PlayerStoreDataEvent$this->plugin$player );
                
    $this->getServer()->getPluginManager()->callEvent$event );
                
    $this->getPlugin()->getLogger()->info"Stored data to array" );
            
                return 
    true;
            }
    PHP:
    /**
             * @param Player $player
             * @param int    $defaultBalance
             *
             * @return bool
             */
            
    public function createAccount Player $player$defaultBalance )
            {
            
                
    /** @var string $name */
                
    $name $player->getName();
                
    /** @var UUID $uuid */
                
    $uuid $player->getUniqueId();
                
    /** @var string $address */
                
    $address $player->getAddress();
                if ( isset( 
    $this->getManager()->existingPlayer[ (string)$uuid ] ) ) {
                    return 
    true;
                }
                
    $currentDate date'Y-m-d H:i:s' );
                
    $this->connector->executeInsertQueries::CREATE_ACCOUNT, [
                    
    "uuid" => (string)$uuid,
                    
    "name" => $name,
                    
    "address" => $address,
                ] );
            
                
    $this->getManager()->storePlayerData$player );
            
                
    $this->getPlugin()->getLogger()->info"created account for " $name );
            
                return 
    true;
            }
     
    Last edited: Feb 11, 2020
  2. SOFe

    SOFe Administrator Staff Member PMMP Team Poggit Admin

    Messages:
    1,968
    GitHub:
    sof3
    Can you describe your problem better? It's not apparent what wrong
     
  3. Levi

    Levi Skeleton

    Messages:
    955
    GitHub:
    captainleviftw
    There are times when player data (from database) is not going into the array which results error when I try to use the player data from the array. I tried fixing this by making a check (if the player data is in the array already )before using the player data.
     
  4. SOFe

    SOFe Administrator Staff Member PMMP Team Poggit Admin

    Messages:
    1,968
    GitHub:
    sof3
    What exactly are the times you want to use the player data? Consider cancelling those events, ignoring those events or postponing the handling on a case by case basis.
     
  5. Levi

    Levi Skeleton

    Messages:
    955
    GitHub:
    captainleviftw
    When player joins the server
     
  6. Fadhel

    Fadhel Witch

    Messages:
    68
    GitHub:
    dimbis
    what's the error
     
  7. Levi

    Levi Skeleton

    Messages:
    955
    GitHub:
    captainleviftw
    player uuid not found in array
     
  8. SOFe

    SOFe Administrator Staff Member PMMP Team Poggit Admin

    Messages:
    1,968
    GitHub:
    sof3
    Do other events depend on what you initialized in join event? If not, simply delay the event execution until data are ready. A promise like API would help, such as await-generator
     
  9. Levi

    Levi Skeleton

    Messages:
    955
    GitHub:
    captainleviftw
    Yes it does. Events like PlayerChatEvent, scoreboard and some commands
     
  10. SOFe

    SOFe Administrator Staff Member PMMP Team Poggit Admin

    Messages:
    1,968
    GitHub:
    sof3
    For example, you can have a class like this for each player:
    PHP:
    class PlayerQueue {
        private 
    $data;
        private 
    $queue;

        public function 
    onDataReady($data){
            
    $this->data=$data;
            foreach(
    $this->queue as $run$run($data);
        }
        public function 
    execute(callable $run){
            if(isset(
    $this->data)) $run($this->data);
            else 
    $this->queue[] = $run;
        }
    }
    Pass [$queue, "onDataReady"] to libasynql's onSuccess function.

    Note that you should not mutate the $event object in the closure you pass to $queue->execute(), because the code may be executed *after* the event handler has completed, and mutating the event object (like cancelling events) won't do anything because its effects have already happened at this point.
    The best way is to cancel those events when player data are not ready, e.g. disallow player from chatting, moving, etc. if some permission checks requiring the data could not be performed yet.
    On the other hand, if your event handler doesn't need to mutate the event, e.g. when another player died and you want to check if this player is in the same team as the dead player (to receive notification), you could just ignore the event (or skip this player if it's in a loop).
    Or even better, if it's just an event handler for logging, you might just schedule (using the queue class above) to handle the event later.

    Think about auth plugins. Many actions cannot be done without the player authenticating first. This is essentially the same thing.
     
    Levi likes this.
  11. Levi

    Levi Skeleton

    Messages:
    955
    GitHub:
    captainleviftw
    What do you mean by mutate the event? Change the evnt?
     
  12. SOFe

    SOFe Administrator Staff Member PMMP Team Poggit Admin

    Messages:
    1,968
    GitHub:
    sof3
    i.e. call the setXxx() functions
     
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.