2 * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #include "ByteBuffer.h"
21 #include "WorldPacket.h"
22 #include "UpdateData.h"
26 #include <zlib/zlib.h>
28 UpdateData::UpdateData() : m_blockCount(0)
32 void UpdateData::AddOutOfRangeGUID(std::set
<uint64
>& guids
)
34 m_outOfRangeGUIDs
.insert(guids
.begin(),guids
.end());
37 void UpdateData::AddOutOfRangeGUID(const uint64
&guid
)
39 m_outOfRangeGUIDs
.insert(guid
);
42 void UpdateData::AddUpdateBlock(const ByteBuffer
&block
)
48 void UpdateData::Compress(void* dst
, uint32
*dst_size
, void* src
, int src_size
)
52 c_stream
.zalloc
= (alloc_func
)0;
53 c_stream
.zfree
= (free_func
)0;
54 c_stream
.opaque
= (voidpf
)0;
56 // default Z_BEST_SPEED (1)
57 int z_res
= deflateInit(&c_stream
, sWorld
.getConfig(CONFIG_COMPRESSION
));
60 sLog
.outError("Can't compress update packet (zlib: deflateInit) Error code: %i (%s)",z_res
,zError(z_res
));
65 c_stream
.next_out
= (Bytef
*)dst
;
66 c_stream
.avail_out
= *dst_size
;
67 c_stream
.next_in
= (Bytef
*)src
;
68 c_stream
.avail_in
= (uInt
)src_size
;
70 z_res
= deflate(&c_stream
, Z_NO_FLUSH
);
73 sLog
.outError("Can't compress update packet (zlib: deflate) Error code: %i (%s)",z_res
,zError(z_res
));
78 if (c_stream
.avail_in
!= 0)
80 sLog
.outError("Can't compress update packet (zlib: deflate not greedy)");
85 z_res
= deflate(&c_stream
, Z_FINISH
);
86 if (z_res
!= Z_STREAM_END
)
88 sLog
.outError("Can't compress update packet (zlib: deflate should report Z_STREAM_END instead %i (%s)",z_res
,zError(z_res
));
93 z_res
= deflateEnd(&c_stream
);
96 sLog
.outError("Can't compress update packet (zlib: deflateEnd) Error code: %i (%s)",z_res
,zError(z_res
));
101 *dst_size
= c_stream
.total_out
;
104 bool UpdateData::BuildPacket(WorldPacket
*packet
)
106 ASSERT(packet
->empty()); // shouldn't happen
108 ByteBuffer
buf(4 + (m_outOfRangeGUIDs
.empty() ? 0 : 1 + 4 + 9 * m_outOfRangeGUIDs
.size()) + m_data
.wpos());
110 buf
<< (uint32
) (!m_outOfRangeGUIDs
.empty() ? m_blockCount
+ 1 : m_blockCount
);
112 if(!m_outOfRangeGUIDs
.empty())
114 buf
<< (uint8
) UPDATETYPE_OUT_OF_RANGE_OBJECTS
;
115 buf
<< (uint32
) m_outOfRangeGUIDs
.size();
117 for(std::set
<uint64
>::const_iterator i
= m_outOfRangeGUIDs
.begin(); i
!= m_outOfRangeGUIDs
.end(); ++i
)
119 buf
.appendPackGUID(*i
);
125 size_t pSize
= buf
.wpos(); // use real used data size
127 if (pSize
> 100 ) // compress large packets
129 uint32 destsize
= compressBound(pSize
);
130 packet
->resize( destsize
+ sizeof(uint32
) );
132 packet
->put
<uint32
>(0, pSize
);
133 Compress(const_cast<uint8
*>(packet
->contents()) + sizeof(uint32
), &destsize
, (void*)buf
.contents(), pSize
);
137 packet
->resize( destsize
+ sizeof(uint32
) );
138 packet
->SetOpcode( SMSG_COMPRESSED_UPDATE_OBJECT
);
140 else // send small packets without compression
142 packet
->append( buf
);
143 packet
->SetOpcode( SMSG_UPDATE_OBJECT
);
149 void UpdateData::Clear()
152 m_outOfRangeGUIDs
.clear();