2 * Copyright (C) 2005-2010 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 "ObjectGuid.h"
27 #include <zlib/zlib.h>
29 UpdateData::UpdateData() : m_blockCount(0)
33 void UpdateData::AddOutOfRangeGUID(ObjectGuidSet
& guids
)
35 m_outOfRangeGUIDs
.insert(guids
.begin(),guids
.end());
38 void UpdateData::AddOutOfRangeGUID(ObjectGuid
const &guid
)
40 m_outOfRangeGUIDs
.insert(guid
);
43 void UpdateData::AddUpdateBlock(const ByteBuffer
&block
)
49 void UpdateData::Compress(void* dst
, uint32
*dst_size
, void* src
, int src_size
)
53 c_stream
.zalloc
= (alloc_func
)0;
54 c_stream
.zfree
= (free_func
)0;
55 c_stream
.opaque
= (voidpf
)0;
57 // default Z_BEST_SPEED (1)
58 int z_res
= deflateInit(&c_stream
, sWorld
.getConfig(CONFIG_UINT32_COMPRESSION
));
61 sLog
.outError("Can't compress update packet (zlib: deflateInit) Error code: %i (%s)",z_res
,zError(z_res
));
66 c_stream
.next_out
= (Bytef
*)dst
;
67 c_stream
.avail_out
= *dst_size
;
68 c_stream
.next_in
= (Bytef
*)src
;
69 c_stream
.avail_in
= (uInt
)src_size
;
71 z_res
= deflate(&c_stream
, Z_NO_FLUSH
);
74 sLog
.outError("Can't compress update packet (zlib: deflate) Error code: %i (%s)",z_res
,zError(z_res
));
79 if (c_stream
.avail_in
!= 0)
81 sLog
.outError("Can't compress update packet (zlib: deflate not greedy)");
86 z_res
= deflate(&c_stream
, Z_FINISH
);
87 if (z_res
!= Z_STREAM_END
)
89 sLog
.outError("Can't compress update packet (zlib: deflate should report Z_STREAM_END instead %i (%s)",z_res
,zError(z_res
));
94 z_res
= deflateEnd(&c_stream
);
97 sLog
.outError("Can't compress update packet (zlib: deflateEnd) Error code: %i (%s)",z_res
,zError(z_res
));
102 *dst_size
= c_stream
.total_out
;
105 bool UpdateData::BuildPacket(WorldPacket
*packet
)
107 ASSERT(packet
->empty()); // shouldn't happen
109 ByteBuffer
buf(4 + (m_outOfRangeGUIDs
.empty() ? 0 : 1 + 4 + 9 * m_outOfRangeGUIDs
.size()) + m_data
.wpos());
111 buf
<< (uint32
) (!m_outOfRangeGUIDs
.empty() ? m_blockCount
+ 1 : m_blockCount
);
113 if(!m_outOfRangeGUIDs
.empty())
115 buf
<< (uint8
) UPDATETYPE_OUT_OF_RANGE_OBJECTS
;
116 buf
<< (uint32
) m_outOfRangeGUIDs
.size();
118 for(ObjectGuidSet::const_iterator i
= m_outOfRangeGUIDs
.begin(); i
!= m_outOfRangeGUIDs
.end(); ++i
)
119 buf
<< i
->WriteAsPacked();
124 size_t pSize
= buf
.wpos(); // use real used data size
126 if (pSize
> 100 ) // compress large packets
128 uint32 destsize
= compressBound(pSize
);
129 packet
->resize( destsize
+ sizeof(uint32
) );
131 packet
->put
<uint32
>(0, pSize
);
132 Compress(const_cast<uint8
*>(packet
->contents()) + sizeof(uint32
), &destsize
, (void*)buf
.contents(), pSize
);
136 packet
->resize( destsize
+ sizeof(uint32
) );
137 packet
->SetOpcode( SMSG_COMPRESSED_UPDATE_OBJECT
);
139 else // send small packets without compression
141 packet
->append( buf
);
142 packet
->SetOpcode( SMSG_UPDATE_OBJECT
);
148 void UpdateData::Clear()
151 m_outOfRangeGUIDs
.clear();