Войти
ПрограммированиеФорумИгровая логика и ИИ

Идентификация внутриигровых предметов

#0
14:45, 16 дек 2012

Всем привет! Несколько дней бьюсь над идентификацией предметов, в общем есть БД в ней таблица character и таблица item, в которой записываются все внутриигровые предметы принадлежащие character, как их лучше связать?
Традиционно это был пул числовых идентификаторов, типа Owner="ИД_Персонажа" и ITEM="ИД_Предмета", но встает вопрос об уникальности идентификаторов.
Т.е. если в бд предметы 1,2,3 и 2 предмет будет уничтожен, то останутся 1,3 а идентификатор 2 будет освобожден, так вот как бы мне его использовать дальше, учитывая что сервер может быть перезагружен и ему нужно как-то его узнать, соответственно циклы не прокатят, слишком дорого
Что нибудь подскажите

#1
14:45, 16 дек 2012

Или проще связывать их по имени персонажа? не затратно ли это будет?

#2
15:10, 16 дек 2012

А четырех миллиардов свободных идентификаторов уже не хватает, да?

#3
15:22, 16 дек 2012

Это кривовато. Нужны идентификаторы вида 4000-5000, для обозначения "областей" предметов. одна область - оружее, другая броня и тп

#4
16:06, 16 дек 2012

>Нужны идентификаторы вида 4000-5000, для обозначения "областей" предметов. одна область - оружее, другая броня и тп
вот это кривовато

дополнительная таблица не нужна, у предмета поле owner и индекс  по этому полю - будет достаточно
тип предмета задавать отдельным полем.

#5
16:11, 16 дек 2012

поменял флаг согласно содержанию

#6
18:14, 16 дек 2012

Неуникальный ключ INTEGER owner_id NOT NULL - владелец предмета. По нему делается выборка из базы что в сумке и в банке (сумки расположенные в городе) игрока. В MySQL создаётся через CREATE INDEX (см. гуглпоиск по фразе "mysql create index") либо строчку INDEX внутри описания таблицы (да MySQL такие затейники, 37 способов сделать индекс).

Поле INTEGER item_database_id NOT NULL (не уникальное) - код предмета - содержит код в базе данных описаний предметов.

Поле INTEGER container_id NOT NULL (не уникальное) или можно назвать inventory_id - определяет где лежит предмет: сумка1, сумка2, ..., банк1, банк2, ..., шлем, броня, плечи, трусы, сапоги, меч левый, меч правый/щит.

Уникальный ключ INTEGER item_id NOT NULL PRIMARY KEY - целое число код предмета в базе. По нему создаётся предмет в игровом мире и делаются все операции вплоть до уничтожения предмета. Сумка игрока содержит именно эти ключи. Уникальность предмета проверяется по этому ключу.  В MySQL создаётся через CREATE UNIQUE INDEX (см. гуглпоиск по фразе "mysql create unique index") или аттрибут поля PRIMARY KEY

У автора проблемы с пониманием реляционной модели данных и SQL. Можно почитать пару глав какой-нибудь умной книги.

#7
18:20, 16 дек 2012

Я вообще не об этом спрашиваю. Я не спрашиваю как мне спроектировать БД. Я спрашиваю каким мне образом хранить и пользоваться пулом уникальных идентификаторов.
Мне нужно создать пул уникальных идентификаторов и их использовать. Я не до конца понимаю каким лучше образом этот пул сделать, проверка на существование идентификатора, его занятость

#8
19:03, 16 дек 2012

ну раз тебе нужны костыли взамен стандартных средств субд, держи:

создавай и регулярно(раз в час/день сам подбирай) обновляй списки свободных айди по категориям предмета. при добавлении предмета бери первый из этого списка и удаляй его. можно также при удалении предмета добавлять его в соответствующий список свободных.

зы. как-то так делали в еве, но потом долго ругались.

#9
19:26, 16 дек 2012

а BIGINT UNSIGNED NOT NULL AUTO_INCREMENT не поможет?

#10
19:33, 16 дек 2012

Все предлагают либо самые очевидные решения, либо отвечают на свой собственный вопрос.
Всем спасибо. Больше за топиком не слежу.

#11
19:56, 16 дек 2012

cr3a70r
> Т.е. если в бд предметы 1,2,3 и 2 предмет будет уничтожен, то останутся 1,3 а
> идентификатор 2 будет освобожден, так вот как бы мне его использовать дальше,
> учитывая что сервер может быть перезагружен и ему нужно как-то его узнать,
> соответственно циклы не прокатят, слишком дорого
У автора непонимание принципов уникальных монотонно растущих ключей.
Сажи топику ;)

#12
21:31, 16 дек 2012

Пойдет?

public final class IDGenerator {

    private int index , length;
    private int[ ] free;

    public IDGenerator() {}

    public final int get() {
        return this.length == 0 ? this.index++ : this.free[ --this.length ];
    }

    public final void release(final int id) {
        if ( this.free == null ) this.free = new int[ 16 ];
        else if ( this.free.length == this.length ) {
            final int[ ] t = new int[ this.length + 16 ];
            System.arraycopy( this.free , 0 , t , 0 , this.length );
            this.free = t;
        }
        this.free[ this.length ] = id;
        this.sort( this.length++ );
    }

    private final void sort(final int idx) {
        if ( idx == 0 ) return;
        if ( this.free[ idx ] > this.free[ idx - 1 ] ) {
            final int t = this.free[ idx ];
            this.free[ idx ] = this.free[ idx - 1 ];
            this.free[ idx - 1 ] = t;
            this.sort( idx - 1 );
        }
    }

    public final void clear() {
        this.length = this.index = 0;
    }

    public final void dispose() {
        this.clear( );
        this.free = null;
    }


}
#13
22:54, 16 дек 2012

cr3a70r
> cr3a70r
возьми 64битный идентификатор. и генерируй последовательно и не парься.
Даже если предположить что в секунду будишь генерировать 4294967296 ID  тебе 64бит хватит на 136.+лет.

+ по ID можно восстановить последовательность появления ID.

ПрограммированиеФорумИгровая логика и ИИ

Тема в архиве.