Загрузка Clan Mark

  • Автор темы Автор темы lvlkoo
  • Дата начала Дата начала

lvlkoo

Выдающийся
Меценат
Сообщения
64
Розыгрыши
0
Решения
2
Репутация
6
Реакции
40
Баллы
1 325
Помогите пожалуйста разобраться с загрузкой большого значка клана
Клиент говорит что нужен 256х256 24\32 битовый bmp или tga, сделал такой файл, пытаюсь грузить, получаю RequestExSetPledgeCrestLarge с размером файла = 0 (первые 4 байта в пакете должны передавать размер значка)

Что я делаю не так? У меня проблема с файлом или с клиентом?
418-ый протокол, приложил файл который я пытался загрузить для теста


UPD: на хостинг картика всеравно лягла как png, у меня она в формате bmp
 
Решение
Помогите пожалуйста разобраться с загрузкой большого значка клана
Клиент говорит что нужен 256х256 24\32 битовый bmp или tga, сделал такой файл, пытаюсь грузить, получаю RequestExSetPledgeCrestLarge с размером файла = 0 (первые 4 байта в пакете должны передавать размер значка)

Что я делаю не так? У меня проблема с файлом или с клиентом?
418-ый протокол, приложил файл который я пытался загрузить для теста


UPD: на хостинг картика всеравно лягла как png, у меня она в формате bmp
разве?
если ничего не меняли то первое d в пришедшем пакете - это номер части данных по значку, далее еще одно d, не помню для чего (я его к примеру просто считываю но не использую) и уже следующим идет d c количеством байт...
Кто у вас автор сборки и почему используете large?
256×256 это не размер, а цветовая раздельность в формате BMP

В 418 (assassin который вышел года 2 назад) на ессенсе значки клана обычные сейчас без значка альянса.
 
В 418 (assassin который вышел года 2 назад) на ессенсе значки клана обычные сейчас без значка альянса.
В данном случае у меня не ессенс а лайв того времени (Source of Flame) в котором судя по всему есть возможность загрузить большой значек который будет отображаться на флагах и т.д

Исходники мобиуса

256×256 это не размер
В данном случае это именно размер, 256 на 256 пикселей, 256 цвет там для обычного мелкого значка

1710785945210.webp
 
Помогите пожалуйста разобраться с загрузкой большого значка клана
Клиент говорит что нужен 256х256 24\32 битовый bmp или tga, сделал такой файл, пытаюсь грузить, получаю RequestExSetPledgeCrestLarge с размером файла = 0 (первые 4 байта в пакете должны передавать размер значка)

Что я делаю не так? У меня проблема с файлом или с клиентом?
418-ый протокол, приложил файл который я пытался загрузить для теста


UPD: на хостинг картика всеравно лягла как png, у меня она в формате bmp
разве?
если ничего не меняли то первое d в пришедшем пакете - это номер части данных по значку, далее еще одно d, не помню для чего (я его к примеру просто считываю но не использую) и уже следующим идет d c количеством байт данных
ну и чтобы получить полностью всю эмблему, после принятия каждого пакета и обработки данных слать в ответ запрос на получение следующей части данных и так пока все не будет получено и не будет возможность из всех частей уже собрать и сохранить полную эмблему.
Java:
package l2p.gameserver.network.c2s.pledge;

import l2p.gameserver.cache.CrestCache;
import l2p.gameserver.cache.CrestCache.CrestBuilderHolder;
import l2p.gameserver.config.ClanConfig;
import l2p.gameserver.enums.clans.ClanPrivType;
import l2p.gameserver.model.Player;
import l2p.gameserver.model.clan.Clan;
import l2p.gameserver.network.c2s.L2GameClientPacket;
import l2p.gameserver.network.components.SystemMsg;
import l2p.gameserver.network.s2c.pledge.ExSetPledgeEmblemAck;

public class RequestSetPledgeEmblem extends L2GameClientPacket
{
    private static final int _dataSize = 14336;

    private int _length, _part;
    private byte[] _data;

    @Override
    protected void readImpl()
    {
        _part = readD();
        readD();
        _length = readD();

        if (_length <= _dataSize && _length == _buf.remaining())
        {
            _data = new byte[_length];
            readB(_data);
        }
    }

    @Override
    protected void runImpl()
    {
        Player player = getPlayer();

        if (player == null)
            return;

        if (_length < 0 || _length > _dataSize)
            return;

        if (!player.hasClanPriv(ClanPrivType.CL_EDIT_CREST))
        {
            player.sendPacket(SystemMsg.YOU_ARE_NOT_AUTHORIZED_TO_DO_THAT);
            return;
        }

        Clan clan = player.getClan();

        if (clan == null)
            return;

        if (_part == 0 && (clan.getLastLargeCrestRegisterTime() + ClanConfig.SET_LARGE_CREST_PERIOD) > System.currentTimeMillis())
        {
            player.sendPacket(SystemMsg.YOU_CAN_REGISTER_A_CLAN_MARK_ONLY_ONCE_EVERY_15_MINUTES);
            return;
        }

        boolean update = false;
        int crestId = 0;

        if (_length != 0 && _data != null)
        {
            player.sendPacket(new ExSetPledgeEmblemAck(_part));
            CrestBuilderHolder crestHolder;

            if (_length == _dataSize)
            {
                if (_part == 0)
                {
                    CrestCache.getInstance().createCrestLargeBuffer(player.getClanId(), _data);
                }
                else
                {
                    crestHolder = CrestCache.getInstance().getCrestLargeBuffer(player.getClanId());
                    crestHolder.appendToBuffer(_data);
                }

                return;
            }

            crestHolder = CrestCache.getInstance().getCrestLargeBuffer(player.getClanId());
            crestHolder.appendToBuffer(_data);
            crestId = CrestCache.getInstance().savePledgeCrestLarge(clan.getId(), crestHolder.getCrest());
            player.sendPacket(SystemMsg.THE_CLAN_MARK_WAS_SUCCESSFULLY_REGISTERED);
            update = true;
        }
        else if (clan.getCrestLargeId() > 0)
        {
            CrestCache.getInstance().removePledgeCrestLarge(clan.getId());
            player.sendPacket(SystemMsg.THE_CLAN_MARK_HAS_BEEN_DELETED);
            update = true;
        }

        if (update)
        {
            if (crestId > 0)
                clan.setLastLargeCrestRegisterTime();

            clan.setCrestLargeId(crestId);
            clan.broadcastClanStatus(false, true, false);
        }

        CrestCache.getInstance().removeCrestLargeBuffer(player.getClanId());
    }
}
 
Решение
Gaikotsu, я подумал что там все по аналогии с RequestSetPledgeCrest для обычного значка, но видимо у мобиуса RequestExSetPledgeCrestLarge реализован не правильно.

Спасибо большое за подсказку,
 
I hope these will help you
Java:
public final class RequestExSetPledgeCrestLarge extends GameClientPacket
{
    private int                _crestPart, _crestLeght, _length;
    private byte[]            _data;
    public static final int    ALLY_CREST_SIZE            = 192;
    public static final int    CREST_SIZE                = 256;
    public static final int    LARGE_CREST_PART_SIZE    = 14336;
   
    @SuppressWarnings("unused")
    @Override
    protected void readImpl()
    {
        _crestPart = readD();
        _crestLeght = readD();
        _length = readD();
        if (_length <= LARGE_CREST_PART_SIZE && _length == _buf.remaining())
        {
            _data = new byte[_length];
            readB(_data);
        }
    }
   
    @Override
    protected void runImpl()
    {
        final Player activeChar = getClient().getActiveChar();
        if (activeChar == null)
        {
            return;
        }
        final Clan clan = activeChar.getClan();
        if (clan == null)
        {
            return;
        }
        int crestId = 0;
        if (_data != null)
        {
            crestId = CrestHolder.getInstance().savePledgeCrestLarge(clan.getId(), _crestPart, _crestLeght, _data);
            if (crestId > 0)
            {
                activeChar.sendPacket(SystemMessageId.CLAN_EMBLEM_WAS_SUCCESSFULLY_REGISTERED);
                clan.setCrestLargeId(crestId);
                clan.broadcastClanStatus();
            }
            activeChar.sendPacket(new ExSetPledgeEmblemAck(_crestPart));
        }
        else if (clan.getCrestLargeId() > 0)
        {
            CrestHolder.getInstance().removePledgeCrestLarge(clan.getId());
            clan.setCrestLargeId(crestId);
            clan.broadcastClanStatus();
        }
    }
}
Java:
public class ExSetPledgeEmblemAck extends GameServerPacket
{
    private final int _part;
   
    public ExSetPledgeEmblemAck(int part)
    {
        _part = part;
    }
   
    @Override
    protected void writeImpl()
    {
        writeD(_part);
    }
}
Java:
public class ExPledgeEmblem extends GameServerPacket
{
    private final int        _clanId, _crestId;
    private int                _crestPart;
    private int                _totalSize;
    private final byte[]    _data;
   
    public ExPledgeEmblem(int crestId, byte[] data)
    {
        _crestId = crestId;
        _data = data;
        _clanId = 0;
    }
   
    public ExPledgeEmblem(int crestId, byte[] data, int clanId, int chunkId)
    {
        _crestId = crestId;
        _data = data;
        _clanId = clanId;
        _crestPart = chunkId;
    }
   
    public ExPledgeEmblem(int clanId, int crestId, int crestPart, int totalSize, byte[] data)
    {
        _clanId = clanId;
        _crestId = crestId;
        _crestPart = crestPart;
        _totalSize = totalSize;
        _data = data;
    }
   
    @Override
    protected boolean canWriteHF()
    {
        return _clanId == 0;
    }
   
    @Override
    protected final void writeSalvationImpl()
    {
        writeD(Config.REQUEST_ID);
        writeD(_clanId);
        writeD(_crestId);
        writeD(_crestPart);
        writeD(_totalSize);
        writeD(_data.length);
        writeB(_data);
    }
   
    @Override
    protected void writeImpl()
    {
        writeD(0x00);
        writeD(_crestId);
        if (_data != null)
        {
            writeD(_data.length);
            writeB(_data);
        }
        else
        {
            writeD(0x00);
        }
    }
}
Java:
    private final TIntObjectMap<TIntObjectMap<byte[]>>    _pledgeCrestLarge        = new TIntObjectHashMap<>();
    private final TIntObjectMap<TIntObjectMap<byte[]>>    _pledgeCrestLargeTemp    = new TIntObjectHashMap<>();
    private final TIntIntMap                            _pledgeCrestLargeId        = new TIntIntHashMap();


    private void loadLargeCrests()
    {
        Connection            con            = null;
        PreparedStatement    statement    = null;
        ResultSet            rset        = null;
        int                    pledgeId, crestId, crestPartId;
        byte[]                crest;
        int                    count        = 0;
        try
        {
            con = DatabaseFactory.getInstance().getConnection();
            statement = con.prepareStatement("SELECT clan_id, data FROM clan_largecrests WHERE crest_part=0 AND data IS NOT NULL");
            rset = statement.executeQuery();
            while (rset.next())
            {
                count++;
                pledgeId = rset.getInt("clan_id");
                crest = rset.getBytes("data");
                crestId = getCrestId(pledgeId, crest);
                _pledgeCrestLargeId.put(pledgeId, crestId);
            }
            DbUtils.close(statement, rset);
            statement = con.prepareStatement("SELECT clan_id, crest_part, data FROM clan_largecrests WHERE data IS NOT NULL ORDER BY clan_id asc, crest_part asc");
            rset = statement.executeQuery();
            while (rset.next())
            {
                pledgeId = rset.getInt("clan_id");
                crestPartId = rset.getInt("crest_part");
                crest = rset.getBytes("data");
                if (!_pledgeCrestLargeId.containsKey(pledgeId))
                {
                    warn("Clan large crest has crashed. Clan ID: " + pledgeId);
                    continue;
                }
                crestId = _pledgeCrestLargeId.get(pledgeId);
                TIntObjectMap<byte[]> crestMap = _pledgeCrestLarge.get(crestId);
                if (crestMap == null)
                {
                    crestMap = new TIntObjectHashMap<>();
                }
                crestMap.put(crestPartId, crest);
                _pledgeCrestLarge.put(crestId, crestMap);
            }
            DbUtils.close(statement, rset);
            info("CrestCache: Loaded " + count + " Large crests");
        }
        catch (final SQLException e)
        {
            warn("There was an error while loading large crests from database:", e);
        }
    }


    public void removePledgeCrestLarge(int pledgeId)
    {
        try
        {
            _pledgeCrestLarge.remove(_pledgeCrestLargeId.remove(pledgeId));
        }
        finally
        {}
        Connection            con            = null;
        PreparedStatement    statement    = null;
        try
        {
            con = DatabaseFactory.getInstance().getConnection();
            statement = con.prepareStatement("DELETE FROM clan_largecrests WHERE clan_id=?");
            statement.setInt(1, pledgeId);
            statement.execute();
        }
        catch (final Exception e)
        {
            _log.log(Level.FINE, e.getMessage(), e);
            e.printStackTrace();
        }
        finally
        {
            DbUtils.closeQuietly(con, statement);
        }
    }
   
    public static int getByteMapSize(TIntObjectMap<byte[]> map)
    {
        int size = 0;
        if (map != null && !map.isEmpty())
        {
            for (final byte[] tempCrest : map.valueCollection())
            {
                size += tempCrest.length;
            }
        }
        return size;
    }

    public int savePledgeCrestLarge(int pledgeId, int crestPart, int crestTotalSize, byte[] data)
    {
        int crestId = 0;
        try
        {
            TIntObjectMap<byte[]> crest = _pledgeCrestLargeTemp.get(pledgeId);
            if (crestPart == 0)
            {
                _pledgeCrestLargeTemp.remove(pledgeId);
                crest = new TIntObjectHashMap<>();
            }
            if (crest != null)
            {
                crest.put(crestPart, data);
                final int tempSize = getByteMapSize(crest);
                if (crestTotalSize > tempSize)
                {
                    _pledgeCrestLargeTemp.put(pledgeId, crest);
                }
                else if (crestTotalSize < tempSize)
                {
                    _pledgeCrestLargeTemp.remove(pledgeId);
                    _log.log(Level.WARNING, "Error while save pledge large crest, clan_id: " + pledgeId + ", crest_part: " + crestPart + ", crest_total_size: " + crestTotalSize + ", temp_size: " + tempSize);
                }
                else
                {
                    crestId = getCrestId(pledgeId, crest.get(0));
                    _pledgeCrestLargeId.put(pledgeId, crestId);
                    _pledgeCrestLarge.put(crestId, crest);
                    Connection            con            = null;
                    PreparedStatement    statement    = null;
                    try
                    {
                        con = DatabaseFactory.getInstance().getConnection();
                        statement = con.prepareStatement("DELETE FROM clan_largecrests WHERE clan_id=?");
                        statement.setInt(1, pledgeId);
                        statement.execute();
                        DbUtils.closeQuietly(statement);
                        for (final TIntObjectIterator<byte[]> iterator = crest.iterator(); iterator.hasNext();)
                        {
                            iterator.advance();
                            statement = con.prepareStatement("REPLACE INTO clan_largecrests(clan_id, crest_part, data) VALUES (?,?,?)");
                            statement.setInt(1, pledgeId);
                            statement.setInt(2, iterator.key());
                            statement.setBytes(3, iterator.value());
                            statement.execute();
                            DbUtils.closeQuietly(statement);
                        }
                    }
                    catch (final Exception e)
                    {
                        _log.log(Level.FINE, e.getMessage(), e);
                        e.printStackTrace();
                    }
                    finally
                    {
                        DbUtils.closeQuietly(con, statement);
                    }
                    _pledgeCrestLargeTemp.remove(pledgeId);
                }
            }
            else
            {
                _log.log(Level.WARNING, "Error while save pledge large crest, clan_id: " + pledgeId + ", crest_part: " + crestPart + ", crest_total_size: " + crestTotalSize);
            }
        }
        finally
        {}
        return crestId;
    }
SQL:
-- ----------------------------
-- Table structure for clan_largecrests
-- ----------------------------
DROP TABLE IF EXISTS `clan_largecrests`;
CREATE TABLE `clan_largecrests`  (
  `clan_id` int(11) NOT NULL DEFAULT 0,
  `crest_part` tinyint(3) UNSIGNED NOT NULL DEFAULT 0,
  `data` blob NULL DEFAULT NULL,
  PRIMARY KEY (`clan_id`, `crest_part`) USING BTREE
) ENGINE = MyISAM CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Dynamic;

SET FOREIGN_KEY_CHECKS = 1;
 
Кстати можно хранить на сервере для эмблемы в виде файлов, т.к. хранить в бд по 64кб данных для каждой такой эмблемы, ну как-то такое.
Проще хранить их в виде dds-файлов (коими они и являются) в отдельной папке сервера, загружая и кэшируя в память при запуске сервера.
 
Последнее редактирование:
Назад
Сверху Снизу