[Achievements] Core 🏆

[Achievements] Core 🏆 Release 1.2

Romanov

Участник
Сообщения
404
Реакции
40
А что не так? -1 значит выполнено
то что он выполнил 6 заданий
1669143142033.png

в бд при этом -1 всего два задания
Режим стоит "continue" "0"
и 331 килов. у него было до этого бага около 2к килов и 4 достижения
1669143379284.png

зеленое норм
красное баг
чтобы получить 6 достижений надо намного больше килов
Я понимаю все в бд должно быть как у чела с никрм корвус. Достижение получил в столбце - 1 без сброса очков.
А на скрин какая-то жесть)
 
Последнее редактирование:

fantom00141

Участник
Сообщения
75
Реакции
5
Такой вопрос, триггер "condition" может содержать одновременно несколько условий выполнения? Например
"condition" "headshot;weapon = glock"

Пробовал так сделать, не сработало
 

Rimmer

Помогаю новичкам / Переводчик / Тестер / Заказчик
Сообщения
1,368
Реакции
753
  • Автор ресурса
  • #84
то что он выполнил 6 заданий Посмотреть вложение 104936
в бд при этом -1 всего два задания
Режим стоит "continue" "0"
и 331 килов. у него было до этого бага около 2к килов и 4 достижения
Посмотреть вложение 104937
зеленое норм
красное баг
чтобы получить 6 достижений надо намного больше килов
Я понимаю все в бд должно быть как у чела с никрм корвус. Достижение получил в столбце - 1 без сброса очков.
А на скрин какая-то жесть)
А вы сбрасывали базу в новом обновлении?
Сообщения автоматически склеены:

"condition" "headshot;weapon = glock"
Записал
NOTED.gif
 
Последнее редактирование:

Romanov

Участник
Сообщения
404
Реакции
40
А вы сбрасывали базу в новом обновлении?
Сообщения автоматически склеены:


Записал
NOTED.gif
конечно
на новой базе все. подправил названия достижений добавив в место пробела _ и все
у меня ина старой версии тож самое было до релиза которая. могу дропнуть еще раз бд. всеравно в этой базе 80% все криво занесено
1669220967544.png

чистая потестирую еще
 
Последнее редактирование:

fantom00141

Участник
Сообщения
75
Реакции
5
конечно
на новой базе все. подправил названия достижений добавив в место пробела _ и все
у меня ина старой версии тож самое было до релиза которая. могу дропнуть еще раз бд. всеравно в этой базе 80% все криво занесено
Посмотреть вложение 104974
чистая потестирую еще
У меня база работает идеально. Может вы меняли настройки в файле achievements.txt после сброса бд? Тогда такое может быть
 

Romanov

Участник
Сообщения
404
Реакции
40
У меня база работает идеально. Может вы меняли настройки в файле achievements.txt после сброса бд? Тогда такое может быть
Нет все настроено было, есть вариант сбросил бд в момент когда сервер ещё был включён, слишком быстро все сделал просто в момент перезагрузки сервера . Вчера отключил сервер, очистил бд
 

-=|УЧЕНИК|=-

вся жизнь,сплошной цирк.
Сообщения
876
Реакции
212
А если игрок дошел до максимального уровня,то что тогда?
Остается все так-же? Если да,то не плохо было бы,чтоб достижения сбрасывались у игрока который дошел до максимального уровня.И опять все с начала.
Можно еще добавить оверлей,при повышении достижении.
Ну это я так к слову,возможно бред написал)
 

Romanov

Участник
Сообщения
404
Реакции
40
1669547362782.png

1669547419830.png

вот такая ошибка в переводе вроде бы все норм
и опять
1669547455677.png
 

YoungDizziss

Участник
Сообщения
82
Реакции
10
Не заносит данные в базу и заспамило лог файл
L 11/28/2022 - 13:03:36: [SM] [55] Line 156, d:\Hentai\GitHub\Achievements-Reborn\addons\sourcemod\scripting\achievements.sp::Achievements_OnCoreLoaded
L 11/28/2022 - 13:03:36: [SM] [57] Call_Finish
 

Pisex

Участник
Сообщения
172
Реакции
155
Не заносит данные в базу и заспамило лог файл
L 11/28/2022 - 13:03:36: [SM] [55] Line 156, d:\Hentai\GitHub\Achievements-Reborn\addons\sourcemod\scripting\achievements.sp::Achievements_OnCoreLoaded
L 11/28/2022 - 13:03:36: [SM] [57] Call_Finish
У тебя вроде версия старая

Пингуйте Риммера, я ему скинул фикс ещё позавчера
 

Kruzya

Участник
Сообщения
12,970
Реакции
10,914
  • Команда форума
  • #92
А для чего под каждую ачивку заводить колонку?
 

Kruzya

Участник
Сообщения
12,970
Реакции
10,914
  • Команда форума
  • #94
@Pisex, а колонку-то зачем? Чем реализация обычного KV-хранилища из оригинала не устроила?
 

Pisex

Участник
Сообщения
172
Реакции
155
@Pisex, а колонку-то зачем? Чем реализация обычного KV-хранилища из оригинала не устроила?
В оригинале создается для этого отдельная таблица и туда уже идёт каждая так (Клиент Айди) (Название ачивки) (Значение)
 

Kruzya

Участник
Сообщения
12,970
Реакции
10,914
  • Команда форума
  • #96
@Pisex, я об этом и говорю.
Чем она не устроила-то?
 

Pisex

Участник
Сообщения
172
Реакции
155
@Pisex, я об этом и говорю.
Чем она не устроила-то?
Не слишком ли много будет она занимать если администратор создаст по 50 ачивок и на сервер зайдет 1000 человек, то уже будет не весело 50000 строк, при этом надо ведь при каждом заходе игрока искать их.
Да и просили переделать чтобы веб удобнее было сделать, хз зачем
Да и разве такой способ не более удобен и оптимизирован?
 

Kruzya

Участник
Сообщения
12,970
Реакции
10,914
  • Команда форума
  • #98
Не слишком ли много будет она занимать если администратор создаст по 50 ачивок и на сервер зайдет 1000 человек, то уже будет не весело 50000 строк
Ну, хорошо, давай посчитаем.

50 ачивок, предположим длина ключа каждой -- 128 байт (не помню, сколько допустимая была в том плагине). Значение -- обычный инт (4 байта).
Плюс храним идентификатор юзера (предположим Community ID, да ещё и самым всратым способом -- строкой), 32 байта.
К каждому строковому типу обычно ещё прилагается её длина. Сколько там мускул накидывает для её хранения - не в курсе, но предположим, что 8 байт (64-битное число). Строковых типов у нас два (комьюнити ид и имя ачивки).
Т.е. в максимально худших условиях получим, что одна строка занимает 32 + 8 + 128 + 8 + 4 - 180 байт. Теперь умножаем это число на 50000 - получаем 9000000 байт, или ~9 килобайт.

Это действительно много, когда даже на фришном тарифе Арены выделяется 1гб диска?

при этом надо ведь при каждом заходе игрока искать их
Джоины разрулят, главное индексы грамотно развесить. Тогда будет +- та же скорость, что и от одной таблицы.

Да и просили переделать чтобы веб чтобы удобнее было сделать, хз зачем
В таком варианте веб определенно неудобно будет делать, потому что в текущем мире очень любят через ORM работать с базой. ORM требует заранее объявлять структуру таблицы как-то программно. В той же Symfony это должны быть прямо отдельные классы с руками прописанными property и описанными типами.
Как думаете, получится ли у Вас для Симфы намутить универсальную энтитю без кодогенерации? Сомневаюсь.
Я его позаимствовал с кодовой базы builds.kruzya.me. В этой энтити представлена одна единица готовой сборки плагина под какую-то версию SM, и, возможно, с какими-то доп параметрами компиляции (наличие отладки, например).
PHP:
<?php

namespace App\Entity;

use App\Repository\ArtifactRepository;
use App\Util;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass=ArtifactRepository::class)
 */
class Artifact extends AbstractEntity
{
    /**
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\ManyToOne(targetEntity=Product::class, inversedBy="artifacts")
     * @ORM\JoinColumn(nullable=false)
     */
    private $product_id;

    /**
     * @ORM\Column(type="datetime")
     */
    private $uploaded_at;

    /**
     * @ORM\ManyToMany(targetEntity=Tag::class)
     */
    private $tags;

    /**
     * @ORM\Column(type="string", length=40)
     */
    private $file_hash;

    /**
     * @ORM\Column(type="integer")
     */
    private $file_size;

    /**
     * @ORM\Column(type="string", length=255)
     */
    private $file_name;

    public function __construct()
    {
        $this->tags = new ArrayCollection();
    }

    public function getId(): ?int
    {
        return $this->id;
    }

    public function getProductId(): ?Product
    {
        return $this->product_id;
    }

    public function setProductId(?Product $product_id): self
    {
        $this->product_id = $product_id;

        return $this;
    }

    public function getUploadedAt(): ?\DateTimeInterface
    {
        return $this->uploaded_at;
    }

    public function setUploadedAt(\DateTimeInterface $uploaded_at): self
    {
        $this->uploaded_at = $uploaded_at;

        return $this;
    }

    /**
     * @return Collection|Tag[]
     */
    public function getTags(): Collection
    {
        return $this->tags;
    }

    public function addTag(Tag $tag): self
    {
        if (!$this->tags->contains($tag)) {
            $this->tags[] = $tag;
        }

        return $this;
    }

    public function removeTag(Tag $tag): self
    {
        $this->tags->removeElement($tag);

        return $this;
    }

    public function getFileHash(): ?string
    {
        return $this->file_hash;
    }

    public function setFileHash(string $file_hash): self
    {
        $this->file_hash = $file_hash;

        return $this;
    }

    public function getFileSize(): ?int
    {
        return $this->file_size;
    }

    public function setFileSize(int $file_size): self
    {
        $this->file_size = $file_size;

        return $this;
    }

        public function getFileName(): ?string
    {
        return $this->file_name;
    }

    public function setFileName(string $file_name): self
    {
        $this->file_name = $file_name;

        return $this;
    }

    public function getPublicPath(): string
    {
        if (!$this->getId())
        {
            return '';
        }

        $id = $this->getId();
        $groupId = ($id - ($id % 1000)) / 1000;

        return sprintf('artifacts/%s/%d-%s.bin', dechex($groupId), $id, $this->getFileHash());
    }

    protected function getSerializeData($serializeLevel)
    {
        $data = [
            'id' => $this->getId(),
            'product' => $this->getProductId()->jsonSerialize(self::API_MIN), // чтобы избежать рекурсии (в теле продукта на API_DEFAULT включаются и артифакты)
            'uploaded_at' => Util::serializeDate($this->getUploadedAt()),

            'url' => $this->getPublicPath()
        ];

        if ($serializeLevel >= self::API_DEFAULT)
        {
            $data['file_hash'] = $this->getFileHash();
            $data['file_name'] = $this->getFileName();
            $data['file_size'] = $this->getFileSize();
            $data['tags'] = $this->getTags()->toArray();
        }

        return $data;
    }
}

Ну и ещё пример энтити на C# для дефолтной там ORM - Entity Framework: ModularTelegramBot

Да и разве такой способ не более удобен и оптимизирован?
В чём его удобство заключается?
 

Pisex

Участник
Сообщения
172
Реакции
155
Ну, хорошо, давай посчитаем.

50 ачивок, предположим длина ключа каждой -- 128 байт (не помню, сколько допустимая была в том плагине). Значение -- обычный инт (4 байта).
Плюс храним идентификатор юзера (предположим Community ID, да ещё и самым всратым способом -- строкой), 32 байта.
К каждому строковому типу обычно ещё прилагается её длина. Сколько там мускул накидывает для её хранения - не в курсе, но предположим, что 8 байт (64-битное число). Строковых типов у нас два (комьюнити ид и имя ачивки).
Т.е. в максимально худших условиях получим, что одна строка занимает 32 + 8 + 128 + 8 + 4 - 180 байт. Теперь умножаем это число на 50000 - получаем 9000000 байт, или ~9 килобайт.

Это действительно много, когда даже на фришном тарифе Арены выделяется 1гб диска?


Джоины разрулят, главное индексы грамотно развесить. Тогда будет +- та же скорость, что и от одной таблицы.


В таком варианте веб определенно неудобно будет делать, потому что в текущем мире очень любят через ORM работать с базой. ORM требует заранее объявлять структуру таблицы как-то программно. В той же Symfony это должны быть прямо отдельные классы с руками прописанными property и описанными типами.
Как думаете, получится ли у Вас для Симфы намутить универсальную энтитю без кодогенерации? Сомневаюсь.
Я его позаимствовал с кодовой базы builds.kruzya.me. В этой энтити представлена одна единица готовой сборки плагина под какую-то версию SM, и, возможно, с какими-то доп параметрами компиляции (наличие отладки, например).
PHP:
<?php

namespace App\Entity;

use App\Repository\ArtifactRepository;
use App\Util;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass=ArtifactRepository::class)
 */
class Artifact extends AbstractEntity
{
    /**
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\ManyToOne(targetEntity=Product::class, inversedBy="artifacts")
     * @ORM\JoinColumn(nullable=false)
     */
    private $product_id;

    /**
     * @ORM\Column(type="datetime")
     */
    private $uploaded_at;

    /**
     * @ORM\ManyToMany(targetEntity=Tag::class)
     */
    private $tags;

    /**
     * @ORM\Column(type="string", length=40)
     */
    private $file_hash;

    /**
     * @ORM\Column(type="integer")
     */
    private $file_size;

    /**
     * @ORM\Column(type="string", length=255)
     */
    private $file_name;

    public function __construct()
    {
        $this->tags = new ArrayCollection();
    }

    public function getId(): ?int
    {
        return $this->id;
    }

    public function getProductId(): ?Product
    {
        return $this->product_id;
    }

    public function setProductId(?Product $product_id): self
    {
        $this->product_id = $product_id;

        return $this;
    }

    public function getUploadedAt(): ?\DateTimeInterface
    {
        return $this->uploaded_at;
    }

    public function setUploadedAt(\DateTimeInterface $uploaded_at): self
    {
        $this->uploaded_at = $uploaded_at;

        return $this;
    }

    /**
     * @return Collection|Tag[]
     */
    public function getTags(): Collection
    {
        return $this->tags;
    }

    public function addTag(Tag $tag): self
    {
        if (!$this->tags->contains($tag)) {
            $this->tags[] = $tag;
        }

        return $this;
    }

    public function removeTag(Tag $tag): self
    {
        $this->tags->removeElement($tag);

        return $this;
    }

    public function getFileHash(): ?string
    {
        return $this->file_hash;
    }

    public function setFileHash(string $file_hash): self
    {
        $this->file_hash = $file_hash;

        return $this;
    }

    public function getFileSize(): ?int
    {
        return $this->file_size;
    }

    public function setFileSize(int $file_size): self
    {
        $this->file_size = $file_size;

        return $this;
    }

        public function getFileName(): ?string
    {
        return $this->file_name;
    }

    public function setFileName(string $file_name): self
    {
        $this->file_name = $file_name;

        return $this;
    }

    public function getPublicPath(): string
    {
        if (!$this->getId())
        {
            return '';
        }

        $id = $this->getId();
        $groupId = ($id - ($id % 1000)) / 1000;

        return sprintf('artifacts/%s/%d-%s.bin', dechex($groupId), $id, $this->getFileHash());
    }

    protected function getSerializeData($serializeLevel)
    {
        $data = [
            'id' => $this->getId(),
            'product' => $this->getProductId()->jsonSerialize(self::API_MIN), // чтобы избежать рекурсии (в теле продукта на API_DEFAULT включаются и артифакты)
            'uploaded_at' => Util::serializeDate($this->getUploadedAt()),

            'url' => $this->getPublicPath()
        ];

        if ($serializeLevel >= self::API_DEFAULT)
        {
            $data['file_hash'] = $this->getFileHash();
            $data['file_name'] = $this->getFileName();
            $data['file_size'] = $this->getFileSize();
            $data['tags'] = $this->getTags()->toArray();
        }

        return $data;
    }
}

Ну и ещё пример энтити на C# для дефолтной там ORM - Entity Framework: ModularTelegramBot


В чём его удобство заключается?
Кто-то мне говорил что так будет удобнее, точно не могу сказать, говорили что для веба будет тоже нормально т.к столбцы можно получить с помощью information_schema
Получается провал и надо заново возвращать прошлый вид базы?
 

Kruzya

Участник
Сообщения
12,970
Реакции
10,914
Я пока не говорил, что надо возвращать. Я всё ещё пытаюсь узнать, чем она не устроила-то? Чисто "размером"? :)

Тем более, раз уже сделано так - то это придётся писать апгрейд, чтобы переносить данные с текущей структуры на новую-старую.

говорили что для веба будет тоже нормально т.к столбцы можно получить с помощью information_schema
Ну, если не юзать ORM, и писать сырые запросы к базе, то да, нормально.
А ещё помимо information_schema можно изучить синтаксис SQL, и узнать о существовании команды DESCRIBE:
1669659660604.png
 
Сверху Снизу