powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Как не одеть в один слот две шмотки ?
25 сообщений из 37, страница 1 из 2
Как не одеть в один слот две шмотки ?
    #39639118
AndryG
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
thing(thing_id, pers_id, slot_id, ...) таблица шмоток персонажа. Кому принадлежит, в какой слот одета NULL - шмотка не одета
slot_ref(slot_id, title) справочник шмоток
pers(pers_id, ...) персонажи

При одевании шмотки в слот персонажа, заполняется поле slot_id шмотки

Код: sql
1.
2.
3.
-- Ограничение на два поля, где одно может быть NULL не работает
ALTER TABLE THING ADD CONSTRAINT UNQ1_THING UNIQUE (PERS_ID,SLOT_ID)
Problematic key value is ("PERS_ID" = 49, "SLOT_ID" = NULL).



Есть мысль (но она мне не нравится) вынести одевание шмотк в отдельную таблицу.
dressed_thing(thing_id, slot_id, pers_id) одетые шмотки это мизерная часть от общей массы. Может поле slot_id и лишнее в таблице шмоток. Выборка одетых шмоток - это очень популярный запрос. Напрягает ещё один join в запросах. (поэтому и pers_id сюда добавил, который дублирует ссылку thin.pers_id

Подскажите, пжлст, как сохранить целостность данных?

Ещё идея, но она мне кажется изратной :)
Сделать доп поле вычисляемое f(slot_id, pers_id) и на него повесить ограничение уникальности. pers_id * 100 + slot_id для снятых шмоток будет NULL, для одетых - уникальное для каждого перс/слот значение
...
Рейтинг: 0 / 0
Как не одеть в один слот две шмотки ?
    #39639124
AndryG
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Бредовость бредовой идея с вычисляемым полем подтвердилась - вычисляемое поле не может участвовать в ограничениях. Что вполне логично.
...
Рейтинг: 0 / 0
Как не одеть в один слот две шмотки ?
    #39639129
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AndryG,

Все просто. Разнеси персонажей, шмотки и слоты в 3 разные таблицы.
И добавь еще одну таблицу связей с тремя полями.
...
Рейтинг: 0 / 0
Как не одеть в один слот две шмотки ?
    #39639259
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
YuRockРазнеси персонажей, шмотки и слоты в 3 разные таблицы.

Обычно слоты это атрибуты персонажа, если только игровая механика не разрешает их
переменное количество или две шмотки в одном слоте.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Как не одеть в один слот две шмотки ?
    #39639280
Гаджимурадов Рустам
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DS> Обычно слоты это атрибуты персонажа, если только игровая
DS> механика не разрешает их переменное количество

Зависит от игры и механики, конечно, но если слотов
более 4 (а это почти всегда так) - я бы их атрибутами
(читай - полями, в твоих словах) не делал.

В той же линейке игр HoMM количество слотов было
фиксировано (и, разумеется, увеличивалось с каждой
версией), а вот инвентарь (а-ля сумка с вещами) - был
очень длинный и его в любом случае пришлось бы
хранить в отдельной таблице, что нежелательно, ИМХО.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Как не одеть в один слот две шмотки ?
    #39639303
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Гаджимурадов РустамЗависит от игры и механики, конечно, но если слотов
более 4 (а это почти всегда так) - я бы их атрибутами
(читай - полями, в твоих словах) не делал.

Почему нет? Их всё равно считанное количество. Переодеть вещь, даже занимающую несколько
слотов, в этом случае - один апдейт.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Как не одеть в один слот две шмотки ?
    #39639351
hvlad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AndryGБредовость бредовой идея с вычисляемым полем подтвердилась - вычисляемое поле не может участвовать в ограничениях. Что вполне логично.Но ничто не мешает создать уникальный индекс

PS в суть не вникал :)
...
Рейтинг: 0 / 0
Как не одеть в один слот две шмотки ?
    #39639421
Гаджимурадов Рустам
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DS> Переодеть вещь, даже занимающую несколько
DS> слотов, в этом случае - один апдейт.

Если она будет храниться в отдельной таблице,
то переодеть однослотовую вещь - тоже 1 апдейт.
Многослотовую (такое редкость) - зависит от того,
как описывается сама многослотовость вещи, тоже
несколько вариантов возможно - "снять" её одним
апдейтом можно всегда, а одеть новую - зависит от.

В любом случае количество апдейтов per se тут не
главное, ИМХО, можно несколько апдейтов и через
SP/EB вызывать, не беда. Гнаться надо за select-ами
(т.е. отображением и "использованием", если второе
не "агрегировано" в атрибуты самого персонажа).

Касательно самого вопроса - как сделать уникальность -
очевидно нужен "индекс" на PersId, ThingId, SlotId/SlotNum -
в зависимости от того, как хранятся слоты.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Как не одеть в один слот две шмотки ?
    #39639429
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Гаджимурадов РустамВ любом случае количество апдейтов per se тут не
главное, ИМХО, можно несколько апдейтов и через
SP/EB вызывать, не беда. Гнаться надо за select-ами
(т.е. отображением и "использованием", если второе
не "агрегировано" в атрибуты самого персонажа).

Насколько я в курсе игровой архитектуры, select нагрузка там никакая, поскольку весь
игровой мир полностью хранится в памяти сервера, а из базы данные персонажа подгружаются
только при входе в игру или редких событиях типа открытия персонального хранилища.
Остальное это жёсткая real-time запись протокола изменений мира для обеспечения durability.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Как не одеть в один слот две шмотки ?
    #39639464
Гаджимурадов Рустам
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну уж всяко "открытия персонального хранилища" не могут случаться реже,
чем переодевания шмоток (не "на экране", а которые нужно сохранить в БД).
И уж, конечно, это случается реже, чем основные игровые события - битвы и пр.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Как не одеть в один слот две шмотки ?
    #39639465
AndryG
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Это браузерка. Потому тут тут с БД выгребается все при каждом новом чихе.

Сейчас в игрушке слоты сделаны отдельными полями в табл. персов. И это просто ад кромешный. Чтобы узнать, что шмотка одета/куда одета/не одета, нужно проверить все поля-слоты в таблице юзера и т.д. И слоты геймдиз мечтет добавлять. Некоторые даже временно для ивентов.

Уникальные индексы получется нужны на поля persId-slotId чтобы не одеть две шмотки в один слот и второй на thingId, чтобы не одеть одну шмотку в два слота.

Поле слота в таблице шмоток (thing.slot_id) удобно для выборок. Отдельная таблица (thing_id, pers_id, slot_id) вместо этого поля добавляет гемора в селекты.

А если совместить поле в таблице инвентаря, а работу с отдельной таблицей одетых шмоток сделать на тригерах?
При прописывании thing.slot_id (одевание шмотки) добавлять запись в табличку, при обNULLении thing.slot_id - стирать запись.

Практикуется такой подход для контроля ссылочной целостности?
...
Рейтинг: 0 / 0
Как не одеть в один слот две шмотки ?
    #39639494
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AndryG,

мне не понятно с какого перепуга у тебя slodId может быть NULL. Есть справочник слотов со своими характеристиками и ограничениями по типам шмоток, где slodId - первичный ключ. Есть таблица со шмотками с ключом thing_id. И есть таблица которая связана с персом, где указывается что на нём одето. Так вот в этой таблице должно быть уникальное ограничение (PERS_ID,SLOT_ID) где никаких NULL быть не может. Установка одета шмотка или нет производится апдейтом поля thing_id (NULL - пусто, не NULL одета конктертная шмотка) в таблице одетых шмоток. Две шмотки ты туда ну никак не воткнёшь. А ещё есть таблица со всеми шмотками перса (PERS_ID,thing_id, busy_flag), где busy_flag - флаг надета ли шмотка.
...
Рейтинг: 0 / 0
Как не одеть в один слот две шмотки ?
    #39639497
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AndryGЭто браузерка. Потому тут тут с БД выгребается все при каждом новом чихе.

Не вижу связи. Браузерка рулится точно таким же сервером, которому ничто не мешает хранить
игровой мир (или по крайней мере состояние персонажа) в памяти.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Как не одеть в один слот две шмотки ?
    #39639508
Гаджимурадов Рустам
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AndryG> И слоты геймдиз мечтет добавлять.

Это вполне естесственно.

AndryG> Некоторые даже временно для ивентов.

А это довольно глупо.

AndryG> Сейчас в игрушке слоты сделаны отдельными полями в табл. персов.
AndryG> Уникальные индексы получется нужны на поля persId-slotId чтобы не
AndryG> одеть две шмотки в один слот

Угу.

AndryG> и второй на thingId, чтобы не одеть одну шмотку в два слота.

Угу. А почему собсно это запрещено (если слоты совместимы с вещью)?

> Поле слота в таблице шмоток (thing.slot_id) удобно для выборок.

Видишь ли, в твоём изложении это thing.slot_id - это просто номер
слота, т.е. slot_num. А местный народ привык, что хрень_id - это FK
на таблицу, в которой эта хрень хранится.

> А если совместить поле в таблице инвентаря, а работу с
> отдельной таблицей одетых шмоток сделать на тригерах?

Излагай яснее. Лично я не понял ни первой части вопроса, ни второй.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Как не одеть в один слот две шмотки ?
    #39639688
AndryG
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Спасибо всем за участие!

Справочник слотов перса
Код: sql
1.
2.
3.
4.
5.
CREATE TABLE SLOT_REF (
    SLOT_ID    D_INTEGER NOT NULL /* D_INTEGER = INTEGER */,
    SLOT_TYPE  D_INTEGER NOT NULL /* D_INTEGER = INTEGER */,
    TITLE      D_TITLE NOT NULL /* D_TITLE = VARCHAR(100) */
);



Шмотки и справочник шмоток
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
CREATE TABLE THING (
    THING_ID     D_INTEGER NOT NULL /* D_INTEGER = INTEGER */,
    PROTO        D_INTEGER NOT NULL /* D_INTEGER = INTEGER */,
    PERS_ID      D_INTEGER NOT NULL /* D_INTEGER = INTEGER */,
    SLOT_ID      D_INTEGER /* D_INTEGER = INTEGER */,  в какой слот одета. NULL - снята
-- ...
);

CREATE TABLE THING_REF (
    PROTO          D_INTEGER NOT NULL /* D_INTEGER = INTEGER */,
    TITLE          D_TITLE NOT NULL /* D_TITLE = VARCHAR(100) */,
    SLOT_TYPE      D_INTEGER /* D_INTEGER = INTEGER */, в какой тип слота может быть одета шмотка
-- ...
);



Изначально я хотел обойтись лишь указаной схемой. Поле thing.slot_id содержит либо указатель на слот, в который одета шмотка, либо NULL (шмотка снята). Такой вариант довольно удобен для выборки шмоток, что делается очень часто)
Для обеспечения ссылочной целостности нужен уникальный ключ (thing.pers_id, thing.slot_id) с игнорированием NULL в slot_id. Что сделать невозможно.

Второй вариант, как указали выше, - это отдельная таблица одетых шмоток (pers_id, slot_id, thing_id). Но с этой таблицей неудобными становятся запросы. Потому хочется сохранить поле thing.slot_id, а его модификацию делать через триггеры табл одетых шмоток.

Симонов Денис, почти этот вариант вы и описали.
авторА ещё есть таблица со всеми шмотками перса (PERS_ID,thing_id, busy_flag), где busy_flag - флаг надета ли шмотка.
Мое поле thing.slot_id и есть этот busy_flag. Только указывает дополнительно и слот.

Получилась такая штука.
Код: sql
1.
2.
3.
4.
5.
6.
7.
CREATE TABLE THING_DRESSED (
    PERS_ID   D_INTEGER NOT NULL /* D_INTEGER = INTEGER */,
    SLOT_ID   D_INTEGER NOT NULL /* D_INTEGER = INTEGER */,
    THING_ID  D_INTEGER /* D_INTEGER = INTEGER */
);
ALTER TABLE THING_DRESSED ADD CONSTRAINT PK_THING_DRESSED PRIMARY KEY (PERS_ID, SLOT_ID);
ALTER TABLE THING_DRESSED ADD CONSTRAINT UNQ1_THING_DRESSED UNIQUE (THING_ID);



Изначально таблица одетых шмоток пустая. При одевании шмотки в слот юзера добавляется новая запись либо апдейтится существующая. При снятии шмотки - thing_id устанавливается в null либо удаляется запись.

Запрос для добавления/апдейта записей
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
merge into thing_dressed trg using (
  select
    t.pers_id,
    s.slot_id,
    t.thing_id
  from thing t
    join thing_ref r -- ищем slot_type одеваемой шмотки в справочнике
      on t.proto = r.proto
      and t.thing_id = :thingId
      and (:persId is null or t.pers_id = :persId) -- доп. проверка перса
    join slot_ref s -- выбираем все слоты подходящего типа
      using (slot_type)
    left join thing_dressed d -- выборка, какие слоты заняты
      on d.slot_id = s.slot_id
      and d.pers_id = t.pers_id -- выбираем первый пустой слот, либо первый для замены в нем шмотки на новую
  order by case when d.thing_id is null then 0 else 1 end, s.slot_id -- нам нужна одна запись. Либо первый пустой слот, либо первый слот - в нем мы заменим шмотку на новую
  fetch first 1 row only) src
on trg.pers_id = src.pers_id
  and trg.slot_id = src.slot_id
when not matched then
  insert (pers_id, slot_id, thing_id)
  values (src.pers_id, src.slot_id, src.thing_id)
when matched and (trg.thing_id is null or trg.thing_id <> src.thing_id) then -- предохранитель от одевания одетой шмотки. надо ли
  update set trg.thing_id = src.thing_id



Одевание/раздевание работает. Теперь триггерами на thing_dressed изменять поле thing.slot_id
Ещё добавилось дублирование pers_id. Нужно затычку для их рассогласования предусмотреть - очищать thing_dressed.thing_id при изменении thing.pers_id Дабы на персе не оказалась одетой шмотка после её передачи другому персу.

авторНе вижу связи. Браузерка рулится точно таким же сервером, которому ничто не мешает хранить
игровой мир (или по крайней мере состояние персонажа) в памяти.
Хранить мир в памяти это круто. Только я совсем без понятия, как это делается. Потому наш мир хранится в БД.
...
Рейтинг: 0 / 0
Как не одеть в один слот две шмотки ?
    #39639693
Фотография kdv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AndryGПотому наш мир хранится в БД.
а что, браузер прямо в БД лезет? промежуточного слоя разве нет?
...
Рейтинг: 0 / 0
Как не одеть в один слот две шмотки ?
    #39639887
Гаджимурадов Рустам
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AndryG
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
Справочник слотов перса

CREATE TABLE SLOT_REF (
    SLOT_ID    D_INTEGER NOT NULL /* D_INTEGER = INTEGER */,
    SLOT_TYPE  D_INTEGER NOT NULL /* D_INTEGER = INTEGER */,
    TITLE      D_TITLE NOT NULL /* D_TITLE = VARCHAR(100) */
);

Шмотки и справочник шмоток

CREATE TABLE THING (
    THING_ID     D_INTEGER NOT NULL /* D_INTEGER = INTEGER */,
    PROTO        D_INTEGER NOT NULL /* D_INTEGER = INTEGER */,
    PERS_ID      D_INTEGER NOT NULL /* D_INTEGER = INTEGER */,
    SLOT_ID      D_INTEGER /* D_INTEGER = INTEGER */,  в какой слот одета. NULL - снята
-- ...
);

CREATE TABLE THING_REF (



Смешались в кучу кони, люди... (с)

Сорри, но у Вас каша в голове и в БД. Рано Вам ещё
"хранимые агрегаты" создавать и денормализацию БД
проводить, сначала нормализацию БД нужно сделать.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Как не одеть в один слот две шмотки ?
    #39639929
Фотография Дегтярев Евгений
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Автор, ты игровой сервер не на PHP пишешь?
...
Рейтинг: 0 / 0
Как не одеть в один слот две шмотки ?
    #39640052
AndryG
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Дегтярев Евгений, на нем самом.
...
Рейтинг: 0 / 0
Как не одеть в один слот две шмотки ?
    #39640061
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AndryG,

и как с коннектами к БД выкручиваешься? Это ведь самый дорогой ресурс. В пыхе нет пула коннектов, есть постоянные соединения, которые мягко говоря не очень и не во всех случаях работают. Ты точно не используешь для кеширования прочитанных данных что нибудь из No-SQL?
...
Рейтинг: 0 / 0
Как не одеть в один слот две шмотки ?
    #39640064
AndryG
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Гаджимурадов Рустам, если не лень, можете подробней описать, что не так лошадьми?

И триггер для синхронизации thing_dressed и thing.slot_id
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
CREATE OR ALTER TRIGGER THING_DRESSED_AIUD0 FOR THING_DRESSED
ACTIVE AFTER INSERT OR UPDATE OR DELETE POSITION 0
AS
begin
  -- синхронизация thing.slot_id
  if(not inserting and old.thing_id is not null) then begin
    update thing set slot_id = null where thing_id = old.thing_id;
  end
  if(not deleting and new.thing_id is not null) then begin
    update thing set slot_id = new.slot_id where thing_id = new.thing_id;
  end
end



Пока работает. Спасибо всем за помощь )
...
Рейтинг: 0 / 0
Как не одеть в один слот две шмотки ?
    #39640075
AndryG
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Коннект действительно довольно прожорлив, но не столь ужасен. Много чего кешируется в memcached. Но от коннекта к БД все равно никуда не деться.
...
Рейтинг: 0 / 0
Как не одеть в один слот две шмотки ?
    #39640081
AndryG
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
авторКоннект действительно довольно прожорлив, но не столь ужасен. Много чего кешируется в memcached. Но от коннекта к БД все равно никуда не деться.
Забыл дополнить, что это слова про текущий проект на mysql. На firebird я еще не пробовал "по боевому".
...
Рейтинг: 0 / 0
Как не одеть в один слот две шмотки ?
    #39640223
Гаджимурадов Рустам
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AndryG> если не лень, можете подробней описать, что не так лошадьми?

Я же выше словами описывал.

Шмотки:

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
CREATE TABLE THING
(
    ID - INTEGER PK
    TITLE - VARCHAR
    Price - INTEGER 
    ...
    Stats - если многообразия нет, описываем прямо тут в одном или нескольких полях
          - если статы/эффекты и пр. сложные и пр. - в отдельной таблице c FK на Thing.ID
    ...
    Slot - INTEGER -- в какой тип слота может быть одета шмотка (номер, а не FK),
                                        сугубо для фильтров и одевания. Значения 100 и выше - багажник.
);



"Надетые" шмотки:
Код: sql
1.
2.
3.
4.
5.
6.
CREATE TABLE PersThings
(
    PERS_ID       INTEGER 
    THING_ID      INTEGER
    SLOT          INTEGER -- в какой слот одета
);



"Справочник слотов перса" - отсутствует. Если, конечно, разные
персонажи (по расе, уникальности, уровню и пр.) не могут иметь
разные типы/количества слотов. Если могут - может понадобиться
доп.таблица (а может и нет - зависит от).

Как хранить/обрабатывать многослотовые вещи могу дополнительно
описать, если нужно, там не рокет-саенс. Уникальность вещь-перс я
бы не делал, это глупо. Уникальность вещь-слот для перса делается
очевидно (индексом), но даже это не нужно, ибо уникальность должна
быть перс-слот, т.е. PersThings.PERS_ID + PersThings.SLOT.

При надевании вещи триггером меняются "текущие" характеристики
персонажа, чтобы каждый раз не пересчитывать.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Как не одеть в один слот две шмотки ?
    #39640326
Фотография Дегтярев Евгений
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AndryGДегтярев Евгений, на нем самом.
не тот ты инструмент выбрал и коннект тут не самое болезненное
проблемы, которые ты тут описываешь, быстрее и дешевле решаются именно внутри процесса сервера твоей игры, а какая субд и как там разложены данные дело десятое

зы
я бы смотрел в сторону go, nodejs, java, c# и. т.п.
...
Рейтинг: 0 / 0
25 сообщений из 37, страница 1 из 2
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Как не одеть в один слот две шмотки ?
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]