Проблема с пакетом ChangeWaitType

nesss

Единомышленник
Участник
Сообщения
138
Розыгрыши
0
Решения
3
Репутация
-2
Реакции
14
Баллы
130
Хроники
  1. The 2nd Throne: Gracia
Исходники
Присутствуют
Сборка
Собственная
Всем привет, давно тут не было меня ) В общем к делу. При отправке клиенту пакета
ChangeWaitType, сажу персонажа на землю:
Java:
/**
 * <b>Описание:</b><br>
 * Этот класс содержит в себе пакет данных, предназначенный для отправки клиенту, который содержит данные об измененном
 * статусе ожидания персонажа.
 */
public class ChangeWaitType extends Send {

    private final int id;                   // Уникальный идентификатор персонажа.
    private final WaitType waitType;        // Тип ожидания персонажа.
    private final int x, y, z;              // Координаты местоположения персонажа.

    /**
     * <b>Описание:</b><br>
     * Конструктор для создания нового экземпляра класса.
     * @param character Объект персонажа.
     * @param waitType Тип ожидания персонажа.
     */
    public ChangeWaitType(Character character, WaitType waitType) {

        this.id = character.getId();
        this.waitType = waitType;

        final LocationObject locationObject = character.getLocationObject();
        this.x = locationObject.getX();
        this.y = locationObject.getY();
        this.z = locationObject.getZ();

        write();    // Выполняет расчет размера пакета данных.

    }

    /**
     * <b>Описание:</b><br>
     * Оболочка, в которой формируется пакет данных для отправки клиенту.
     */
    @Override
    public void write() {

        writeByte(0x29);            // Префикс пакета данных.
        writeInt(id);                     // Уникальный идентификатор персонажа.
        writeInt(waitType.ordinal());     // Тип ожидания персонажа.
        writeInt(x);                      // Координата по оси X местоположения персонажа.
        writeInt(y);                      // Координата по оси Y местоположения персонажа.
        writeInt(z);                      // Координата по оси Z местоположения персонажа.

    }

}

Персонаж садиться все хорошо, но сервер получает от клиента левый пакет, постоянно с разным префиксом, даже таким, какого нет в помине.
Потом после того, как я жму еще раз, что-бы персонаж встал, он не всегда встает, а если встает, то любые действия не могу совершить, начал копать, и обнаружил, что после того, как я усаживаю персонажа, приходит мне пакет ValidatePosition, я логирую координаты, которые мне присылает клиент, и там вот такое:

Код:
// Координаты текущие, правильные.
-79788
248343
-3629

// После того, как жму сесть: (То есть присылает пакет левый, как я и писал и как меняет координату Y и Z)
-> [Система] Код - 219.
-79788
218352151
-3724

// Потом жму встать:
-79788
251906583
-3724

// Потом снова сесть:
-> [Система] Код - 243.
-79788
-1073493481
-3783

Ну и потом персонаж вообще перестает реагировать.

Но в момент, когда персонаж передвигается, координаты в ValidatePosition правильные отправляет, с передвижением таких проблем нет.

Что может быть?
 
Проверил другие клиенты, все так же, то есть это не клиент, проверил координаты, в пакет <span>ChangeWaitType</span> отправлял координаты и полученные с ValidatePosition, так ка у меня координата Z на 2-3 отличается, серверная идет по геодате, проверял, может в координате Z нужна координата не пола, где находится персонаж, а пола + высота персонажа, так как думал, что может при посадке, персонаж уменьшает свою координату Z, так как садится, и уходит ниже текстур, и так как в текстуры заходит, появляется баг, все равно проблема не уходит. Думаю может какие данные не хватает клиенту? Пакет UserInfo высылаю как вхожу в мир:

Java:
    /**
     * <b>Описание:</b><br>
     * Оболочка в которой формируется пакет данных для отправки.
     */
    @Override
    public void write() {

        writeByte(0x32);                            // Префикс пакета данных.
        writeInt(location[0]);                            // Координата X персонажа.
        writeInt(location[1]);                            // Координата Y персонажа.
        writeInt(location[2]);                            // Координата Z персонажа.
        writeInt(0x00);                             // Идентификатор корабля (не используем).
        writeInt(objectId);                               // Уникальный идентификатор объекта в мире.
        writeString(name);                                // Имя персонажа.
        writeInt(raceId);                                 // Идентификатор расы персонажа.
        writeInt(sexId);                                  // Идентификатор пола персонажа.
        writeInt(classId);                                // Идентификатор класса персонажа.
        writeInt(level);                                  // Уровень персонажа.
        writeLong(exp);                                   // Количество очков опыта персонажа.
        writeInt(cStr);                                   // Сила персонажа.
        writeInt(cDex);                                   // Ловкость персонажа.
        writeInt(cCon);                                   // Выносливость персонажа.
        writeInt(cInt);                                   // Интеллект персонажа.
        writeInt(cWit);                                   // Мудрость персонажа.
        writeInt(cMen);                                   // Дух персонажа.
        writeInt(maxHp);                                  // Максимальное количество жизненных сил.
        writeInt(curHp);                                  // Текущее количество жизненных сил.
        writeInt(maxMp);                                  // Максимальное количество магических сил.
        writeInt(curMp);                                  // Текущее количество магических сил.
        writeInt(sp);                                     // Количество очков навыков.
        writeInt(curWeight);                              // Текущий вес всех предметов в инвентаре.
        writeInt(maxWeight);                              // Максимальная грузоподъемность.
        writeInt(activeWeapon);                           // Идентификатор активного оружия.

        // Экипировка персонажа - Идентификатор предмета в мире.
        for (final int[] equip : equip) {

            writeInt(equip[0]);

        }

        // Экипировка персонажа - Идентификатор предмета в клиенте.
        for (final int[] equip : equip) {

            writeInt(equip[1]);

        }

        // Экипировка персонажа - Идентификатор аргументации предмета (Не используем).
        for (final int[] _ : equip) {

            writeInt(0x00);

        }

        writeInt(maxTalismans);                           // Максимальное количество талисманов.
        writeInt(slotCloak);                              // Слот для плаща (открыт/закрыт).
        writeInt(pAtk);                                   // Физическая атака.
        writeInt(pAtkSpd);                                // Скорость физической атаки.
        writeInt(pDef);                                   // Физическая защита.
        writeInt(evasion);                                // Шанс уклонения.
        writeInt(accuracy);                               // Точность.
        writeInt(rCrit);                                  // Шанс критической атаки.
        writeInt(mAtk);                                   // Магическая атака.
        writeInt(mAtkSpd);                                // Скорость магической атаки.
        writeInt(pAtkSpd);                                // Скорость физической атаки.
        writeInt(mDef);                                   // Магическая защита.
        writeInt(0x00);                             // PVP флаг (Не используем).
        writeInt(0x00);                             // Карма (Не используем).
        writeInt(speedRun);                               // Скорость бега.
        writeInt(speedWalk);                              // Скорость ходьбы.
        writeInt(speedSwim);                              // Скорость плавания (бег).
        writeInt(speedSwim);                              // Скорость плавания (ходьба).
        writeInt(speedRunRide);                           // Скорость бега верхом.
        writeInt(speedWalkRide);                          // Скорость ходьбы верхом.
        writeInt(speedRunFly);                            // Скорость полета.
        writeInt(speedWalkFly);                           // Скорость полета при ходьбе.
        writeDouble(speedMultiplier);                     // Множитель скорости передвижения.
        writeDouble(speedAtkMultiplier);                  // Множитель скорости атаки.
        writeDouble(radius);                              // Радиус персонажа.
        writeDouble(height);                              // Высота персонажа.
        writeInt(hairStyleId);                            // Идентификатор прически.
        writeInt(hairColorId);                            // Идентификатор цвета волос.
        writeInt(faceId);                                 // Идентификатор лица.
        writeInt(gm);                                     // Статус администратора.
        writeString(title);                               // Титул персонажа.
        writeInt(clanId);                                 // Идентификатор клана.
        writeInt(clanCrestId);                            // Идентификатор герба клана.
        writeInt(allyId);                                 // Идентификатор альянса.
        writeInt(allyCrestId);                            // Идентификатор герба альянса.
        writeInt(relation);                               // Отношения персонажа.
        writeByte(mountType);                             // Тип животного, которое использует персонаж.
        writeByte(privateStoreType);                      // Тип приватного магазина.
        writeByte(canCrystallize);                        // Возможность кристаллизации предметов.
        writeInt(0x00);                             // Количество PK (Не используем).
        writeInt(kills);                                  // Количество убийств.
        writeShort(cubics.size());                        // Количество активных кубиков у персонажа.

        // Список активных кубиков у персонажа.
        for (final Cubic cubic : cubics.values()) {

            writeShort(cubic.getId());

        }

        writeByte(0x00);                            // PartyRoom (Не используем).
        writeInt(abnormalMainEffects);                    // Основные абнормальные эффекты.
        writeByte(moveType);                              // Тип перемещения.
        writeInt(clanPrivileges);                         // Привилегии в клане.
        writeShort(0x00);                           // Рекомендации (Не используем).
        writeShort(0x00);                           // Рекомендации (Не используем).
        writeInt(mountId);                                // Идентификатор призванного животного.
        writeShort(inventorySlot);                        // Максимальное количество слотов инвентаря.
        writeInt(classId);                                // Идентификатор класса.
        writeInt(0x00);                             // Не используемый параметр.
        writeInt(maxCp);                                  // Максимальные боевые силы.
        writeInt(curCp);                                  // Текущие боевые силы.
        writeByte(enchantEffect);                         // Эффект зачарования надетого оружия.
        writeByte(0x00);                            // Свечение команды (Синее и красное) (Не используем).
        writeInt(clanCrestLargeId);                       // Идентификатор большого герба клана.
        writeByte(noble);                                 // Статус дворянина.
        writeByte(clanLeaderAura);                        // Аура лидера клана.
        writeByte(fishing);                               // Статус рыбалки.
        writeInt(fishingLoc[0]);                          // Координата X места рыбалки.
        writeInt(fishingLoc[1]);                          // Координата Y места рыбалки.
        writeInt(fishingLoc[2]);                          // Координата Z места рыбалки.
        writeInt(nameColor);                              // Цвет имени.
        writeByte(run);                                   // Флаг бега.
        writeInt(clanRank);                               // Ранг в клане.
        writeInt(clanSubunit);                            // Подразделение в клане.
        writeInt(titleColor);                             // Цвет титула.
        writeInt(0x00);                             // CursedWeapons (Не используем).
        writeInt(0x00);                             // Идентификатор трансформации (Не используем).
        writeShort(element[0]);                           // Идентификатор типа элемента как основного.
        writeShort(element[1]);                           // Сила атаки основного элемента.
        writeShort(element[2]);                           // Защита от элемента огня.
        writeShort(element[3]);                           // Защита от элемента воды.
        writeShort(element[4]);                           // Защита от элемента ветра.
        writeShort(element[5]);                           // Защита от элемента земли.
        writeShort(element[6]);                           // Защита от элемента святости.
        writeShort(element[7]);                           // Защита от элемента тьмы.
        writeInt(agathionId);                             // Идентификатор агатиона.
        writeInt(glory);                                  // Очки славы.
        writeInt(0x01);                             // Разрешение мини карты на HellBound.
        writeInt(0x00);                             // Система Vitality (Не используем).
        writeInt(abnormalSpecialEffects);                 // Специальные абнормальные эффекты.
        writeInt(0x00);   // Идентификатор территории, где происходит осада, в которой участвует персонаж.
        writeInt(0x00);   // Статус нахождения персонажа на территории, где происходит осада.
        writeInt(0x00);   // Идентификатор территории, где происходит осада, в которой участвует персонаж, если персонаж находится на территории.

    }
 
Тут нужно проверять каждый пакет который отсылается до ChangeWaitType и смотреть именно на тип данных (writeInt/writeDouble/writeByte) . Если отсылать недостаточно значений то обычно будут какие-то проблемы с клиентом как будто шифрование неправильное. Желательно проверить состав пакета в сравнении с уже рабочей сборкой, либо через исходный код.
 
Ну судя по числам у вас смещение где-то где приходят координаты впоследствии на 1 байт между x и y. Что вообще странно, так с Z все нормально и я не помню чтобы X и Y слались где-то отдельно без Z.
 
У меня пакет высылает X,Y и Z как положено в 1 пакете, вот скажем, подбежал я в точку, координаты обновились той точки куда я прибежал, потом жму сесть, отправляю пакет, который я показал в 1 посте, и вот такое получается, получается в самом клиенте что-то либо не хватает? может пакет какой нужно еще отправить ему, какие-то данные, для нормально функционирования достаточно UserInfo? или нужно еще какой обязательный пакет отправлять? ... Так как координаты изменяются непосредственно клиентом, на сервере координаты правильные. Что на них влиять может? Я имею ввиду в самом клиенте, как он расчитывает их? Да и левый пакет с рандомным префиксом приходит сразу после отправки пакета, что-бы персонаж сел, и клиент залагивает. другие дейсвтия типа бежать не работают.
 
Я думаю у вас проблема именно в сервере. На каком-то этапе сервер отсылает клиенту битые координаты вида:

x
[тут один лишний байт]
y
z

и после этого клиент считает их валидными и в последствии пытается двигаться по ним.

Почему и где это происходит не скажу, может быть как и ошибка где-то в пакете, так и какая-нибудь специфика вашего движка сети (непреднамеренное смещение по записывающему буферу например)
 
Мб там переполнение и у тебя инт на «второй круг» уходит?
 
нужно ли в конструкторе вызывать метод write ?
 
я уже все откинул, просто отправляю UserInfo (кроме него не чего не отправляю), вошел в мир, не шевелюсь, жму сесть и все та же проблема. Получается я клиенту отправляю координаты из UserInfo как вхожу в мир и появляюсь в правильной точке. Те же координаты я передаю в пакет <span>ChangeWaitType</span> а обратно мне клиент присылает не верные Y и Z.
нужно ли в конструкторе вызвать метод write ?
Да у меня так рассчитывается размер пакета, там все правильно, все остальные пакеты работают без проблем.
 
Ну вот логи посмотрите какие пакеты шлю, белым это клиент на сервер шлет, красным, это сервер в клиент шлет.
Открываю окно списка действий и жму сесть:

И вот в последнем пакете ValidatePosition получаю те координаты, по Y и Z не правильные. Таким образом, получается я высылаю в клиент координаты местоположения только в пакете UserInfo, и они правильные, так как персонаж в мире появляется в правильном месте.
 
ну то есть первый запрос сесть происходит всегда?
после него приходит пакет ValidatePosition и в нем сразу не те координаты?
входящий пакет ты не обрабатываешь?( на серве координаты не меняются. )
потом ты жмешь встать ( с теми же координатами но уже код "вставания") но перс может сломаться и не вставать уже?
 
чтобы проверить как приходит пакет userInfo можно отправить информацию о атрибутах. она находится в конце пакета и если отразилась в клиенте то все норм( я так мучался с сальва клиентом, там много ячеек добавилось от агатионов всяких)

и еще попробуй в CharacterSelected тоже отправить координаты верные.
 
Система такая, есть движок передвижение персонажа, координаты местоположения во время передвижения вычисляются на каждый такт - 50мс. Сразу скажу движок отлаженный и работает в связке с геодатой, координаты возвращает настоящие, без погрешностей. Пакет ValidatePosition использую для хранения координат клиента на сервере как последнюю валидную точку, что-бы корректировать резкие скачки координат при перемещении, баги ловит, провалы мб в текстурах и т.д. Пакет ValidatePosition всегда приходит после отправке клиенту пакета ChangeWaitType, ну так и должно быть, это норма. Только координаты по Y и Z он присылает левые. пример можешь посмотреть в логах я скидывал. Заметил, что координату по Z он кидает ниже точки текстур земли самой игры. Я что и подумал, я кидаю координаты местоположения персонажа по земле, по слою геодаты, а клиент ее уменьшает и присылает мне уменьшенную координату, ну то есть ниже моей точки. Может он присылая мне те координаты персонажа перемещает в те же координаты, он застревает в текстурах и шлет мне все что угодно. Но пробовал играть с координатой Z и выше ставил и ниже, не чего не помогает. Еще заметил такое, когда я жму бежать, персонаж в точку бежит, если в момент бега я нажму сесть, он сядет, потом жму встать и все отлично, дальше жму бежать или другие действия все отлично. Вот только в момент, когда персонаж стоит, и жму сесть такая проблема. В userInfo все хорошо отправляет, Не тут 100% дело в координатах, которые я отправляю в пакете ChangeWaitType и скорее всего теми координатами, которые уже есть в клиенте на момент отправки пакета ChangeWaitType. Вот у вас в сборках при перемещении координата персонажа сохраняется по низу слоя? или + высота модели персонажа или как? Думаю в этом не точность.
 
Поверхность в клиенте ниже реальной поверхности по геодате. Разница от 8 до 32(зависит от типа сектора). Т.е если вы условно кликаете в точку XYZ, то реальная позиция на сервере в этом месте будет выше. При этом, любое движение, проверки видимости, ступеньки и прочее рассчитываются строго по геокоординатам. Геодвиг должен корректно отрабатывать эту разницу, при получении пакета C_MOVE_BACKWARD_TO_LOCATION
 
Ну как я знаю, от 8 до 48. Дело в том, что ари передвижении, я то отправляю местоположение персонажа в пакете клиенту и все хорошо, персонаж перемещается без проблем, тогда в чем можеи быть проблема, при действии сесть/встать?
 
Движение не валидирует позицию, а лишь задает направление и длину вектора. Точки, которые вы передаете в клиенте не играют никакой роли. Вы можете слать вообще произвольные цифры, просто задавая вектор и персонаж будет бегать без каких-то проблем. Для решения вопросов с рассинхронизацией(когда координаты в клиенте не совпадают с координатами на сервере), клиент при любом изменении позиции актора, шлет пакет с клиентскими координатами. Исходя из данных, полученных в этом пакете, скрвер принимает решение о необходимости синхронизации. Когда вы садитесь в игре, вы шлете в клиент информацию о том, где вы сели на сервере, а клиент аналогично присылает свои координаты в ответ, чтобы сервер проверил, не нужно ли синхронизироваться.
 
так вопрос в том почему клиент присылает кривую координату по Y?

а во время бега ValidatePosition присылается раз в 1.5 сек? там координаты нормальные?

кстати на клиенте Fafurion когда садишься клиент присылает 2 пакета. ValidatePosition и StopRotation
 
Последнее редактирование модератором:
Да в инетрлюде вроде тоже 2 пакета присылает, что-то помню, я реализовал работу данных пакетов, проблема не решилась, добавил для проверки отправку UserInfo после каждого окончания движения, что-бы точно убедится, что все правильно обновляется в клиенте. Все равно проблема не уходит, но как я выяснил, проблема только когда я сижу, когда перемещаюсь, и во время перемещения жму сесть, все работает отлично.
 
видимо проблема в чудо самописном движке передвижения)

нужно его отключить. в EnterWorld пакете все отключить оставить только UserInfo и ActionList пакет. И посмотреть что случится...
 
Не думаю, когда входит персонаж в мир, он не задействует движок передвижения, используется только UserInfo и сражу жму сесть, и та же проблема.
 
Данный сайт использует cookie. Вы должны принять их для продолжения использования. Узнать больше…