Skip to content

New code issue #1

@Dev-TheNorthFace

Description

@Dev-TheNorthFace

I added this to the code: Added warning and error logs: In the createTokenBalance method, a warning message is added if the player already has a token balance. An error message is also logged if the balance creation fails.

Error handling for queries: A callback is used in database calls to check if the actions completed successfully.

Optimized the resolveUuid method: If a player is already in the cache, their UUID is returned immediately; otherwise, a query is performed to retrieve the UUID from the database.

Protection against bad values ​​in the cache and database: Data retrieved from the database (such as the token balance) is checked to ensure it is valid before being used.


`<?php

declare(strict_types=1);

namespace terpz710\tokensapi\api;

use pocketmine\player\Player;
use terpz710\tokensapi\TokensAPI;
use terpz710\tokensapi\event\TokenBalanceChangeEvent;
use poggit\libasynql\DataConnector;
use poggit\libasynql\libasynql;

final class TokenManager {

protected DataConnector $database;
protected array $tokenCache = [];

public function __construct(protected TokensAPI $plugin) {
    $this->plugin = $plugin;
}

public function init(){
    $this->database = libasynql::create($this->plugin, $this->plugin->getConfig()->get("database"), [
        "sqlite" => "database/sqlite.sql",
        "mysql" => "database/mysql.sql"
    ]);

    $this->database->executeGeneric("table.tokens");
}

public function loadPlayerBalance(Player $player){
    $uuid = $player->getUniqueId()->toString();
    $name = $player->getName();

    $this->database->executeSelect("tokens.get", ["uuid" => $uuid], function(array $rows) use ($uuid, $name) {
        $balance = !empty($rows) ? (int) $rows[0]["balance"] : 0;
        $this->tokenCache[$uuid] = ["balance" => $balance, "name" => $name];
    });
}

public function createTokenBalance(Player $player){
    $uuid = $player->getUniqueId()->toString();
    $name = $player->getName();
    $startingAmount = $this->plugin->getConfig()->get("starting-amount");

    if ($this->hasTokenBalance($player)) {
        $this->plugin->getLogger()->warning("Token balance for player {$name} already exists.");
        return;
    }

    $this->tokenCache[$uuid] = ["balance" => $startingAmount, "name" => $name];

    $this->database->executeChange("tokens.create", [
        "uuid" => $uuid,
        "name" => $name,
        "balance" => $startingAmount
    ], function(bool $success) use ($name) {
        if (!$success) {
            $this->plugin->getLogger()->error("Failed to create token balance for player {$name}");
        }
    });
}

public function hasTokenBalance(Player|string $player) : bool{
    $uuid = $this->resolveUuid($player);
    return $uuid !== '' && isset($this->tokenCache[$uuid]);
}

public function getTokens(Player|string $player) : int{
    $uuid = $this->resolveUuid($player);
    return $uuid !== '' ? ($this->tokenCache[$uuid]['balance'] ?? 0) : 0;
}

public function addTokens(Player|string $player, int $amount){
    $uuid = $this->resolveUuid($player);
    if ($uuid === '') return;

    $oldBalance = $this->getTokens($player);
    $newBalance = $oldBalance + $amount;

    $this->tokenCache[$uuid]['balance'] = $newBalance;
    $this->database->executeChange("tokens.add", ["uuid" => $uuid, "amount" => $amount]);

    $event = new TokenBalanceChangeEvent($player, $oldBalance, $newBalance, "add");
    $event->call();
}

public function removeTokens(Player|string $player, int $amount){
    $uuid = $this->resolveUuid($player);
    if ($uuid === '') return;

    $oldBalance = $this->getTokens($player);
    $newBalance = max(0, $oldBalance - $amount);

    $this->tokenCache[$uuid]['balance'] = $newBalance;
    $this->database->executeChange("tokens.remove", ["uuid" => $uuid, "amount" => $amount]);

    $event = new TokenBalanceChangeEvent($player, $oldBalance, $newBalance, "remove");
    $event->call();
}

public function setTokens(Player|string $player, int $amount){
    $uuid = $this->resolveUuid($player);
    if ($uuid === '') return;

    $oldBalance = $this->getTokens($player);
    $newBalance = $amount;

    $this->tokenCache[$uuid]['balance'] = $newBalance;
    $this->database->executeChange("tokens.set", ["uuid" => $uuid, "amount" => $amount]);

    $event = new TokenBalanceChangeEvent($player, $oldBalance, $newBalance, "set");
    $event->call();
}

public function getTopTokens(callable $callback){
    $this->database->executeSelect("tokens.top", [], function(array $rows) use ($callback) {
        $this->tokenCache['top'] = $rows;
        $callback($rows);
    });
}

private function resolveUuid(Player|string $player) : ?string{
    if ($player instanceof Player) {
        return $player->getUniqueId()->toString();
    }

    foreach ($this->tokenCache as $uuid => $data) {
        if (isset($data['name']) && strtolower($data['name']) === strtolower($player)) {
            return $uuid;
        }
    }

    $result = null;
    $this->database->executeSelect("tokens.get_by_name", ["name" => $player], function(array $rows) use (&$result) {
        $result = !empty($rows) ? $rows[0]["uuid"] : null;
    });

    return $result;
}

}`

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions