litenetlib-0952 1.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,457 @@
1
+ """
2
+ Network packet implementation / 网络数据包实现
3
+
4
+ Packets are the fundamental unit of data transfer in LiteNetLib.
5
+ Each packet has a header containing metadata and optional payload data.
6
+
7
+ 数据包是 LiteNetLib 中数据传输的基本单位。
8
+ 每个数据包都有包含元数据的头部和可选的负载数据。
9
+
10
+ Ported from: LiteNetLib/NetPacket.cs (v0.9.5.2)
11
+ """
12
+
13
+ from typing import Optional
14
+ from litenetlib.core.constants import PacketProperty, NetConstants, get_header_size
15
+ from litenetlib.utils.fast_bit_converter import FastBitConverter
16
+
17
+
18
+ class NetPacket:
19
+ """
20
+ Represents a network packet with header and data.
21
+ 表示具有头部和数据的网络数据包。
22
+
23
+ Header structure (first byte) / 头部结构(第一个字节):
24
+ - Bits 0-4: PacketProperty (5 bits, values 0-31) / 数据包属性
25
+ - Bits 5-6: ConnectionNumber (2 bits, values 0-3) / 连接编号
26
+ - Bit 7: Fragmented flag (1 bit) / 分片标志
27
+
28
+ For channeled packets, additional header / 对于通道数据包,额外的头部:
29
+ - Bytes 1-2: Sequence number (ushort) / 序列号
30
+ - Byte 3: Channel ID / 通道 ID
31
+
32
+ For fragmented packets / 对于分片数据包:
33
+ - Bytes 4-5: Fragment ID (ushort) / 分片 ID
34
+ - Bytes 6-7: Fragment Part (ushort) / 分片部分
35
+ - Bytes 8-9: Fragments Total (ushort) / 分片总数
36
+
37
+ C# Reference: NetPacket.cs
38
+ """
39
+
40
+ # Pre-calculated header sizes for each packet property / 每种数据包属性的预计算头部大小
41
+ _header_sizes = {
42
+ prop: get_header_size(prop) for prop in PacketProperty
43
+ }
44
+
45
+ __slots__ = ('_data', '_size', '_user_data')
46
+
47
+ def __init__(self, size_or_property, property_or_size=None, size=None):
48
+ """
49
+ Create a new NetPacket / 创建新的 NetPacket。
50
+
51
+ Args:
52
+ size_or_property: Either packet size in bytes, or a PacketProperty
53
+ 可以是数据包大小(字节)或 PacketProperty
54
+ property_or_size: If first arg is size, this is PacketProperty
55
+ 如果第一个参数是大小,则是 PacketProperty
56
+ size: Data size (only when creating with property)
57
+ 数据大小(仅在用属性创建时)
58
+ """
59
+ # Check if it's a PacketProperty (IntEnum values are int, need special check)
60
+ # 检查是否为 PacketProperty(IntEnum 值是 int,需要特殊检查)
61
+ try:
62
+ # Try to convert to PacketProperty - if successful and second arg is int, it's a property
63
+ # 尝试转换为 PacketProperty - 如果成功且第二个参数是 int,则是属性
64
+ prop = PacketProperty(size_or_property)
65
+ # If second arg is an int (data size), treat first arg as property
66
+ # 如果第二个参数是 int(数据大小),则将第一个参数视为属性
67
+ if property_or_size is None or isinstance(property_or_size, int):
68
+ data_size = property_or_size if property_or_size is not None else 0
69
+ header_size = NetPacket._header_sizes[prop]
70
+ self._data = bytearray(header_size + data_size)
71
+ self._size = len(self._data)
72
+ self._user_data = None
73
+ # Set packet property in the first byte / 在第一个字节中设置数据包属性
74
+ self._data[0] = prop & 0x1F
75
+ return
76
+ except (ValueError, KeyError):
77
+ # Not a valid PacketProperty, treat as size
78
+ # 不是有效的 PacketProperty,视为大小
79
+ pass
80
+
81
+ # Create with size / 使用大小创建
82
+ self._data = bytearray(size_or_property)
83
+ self._size = size_or_property
84
+ self._user_data = None
85
+
86
+ @classmethod
87
+ def from_bytes(cls, data: bytes) -> 'NetPacket':
88
+ """
89
+ Create a packet from existing bytes / 从现有字节创建数据包。
90
+
91
+ Args:
92
+ data: Source bytes / 源字节
93
+
94
+ Returns:
95
+ NetPacket instance / NetPacket 实例
96
+ """
97
+ packet = cls(len(data))
98
+ packet._data[:] = data
99
+ packet._size = len(data)
100
+ return packet
101
+
102
+ @property
103
+ def packet_property(self) -> PacketProperty:
104
+ """
105
+ Get packet property type / 获取数据包属性类型。
106
+
107
+ C#: Property { get { return (PacketProperty)(RawData[0] & 0x1F); } }
108
+ """
109
+ return PacketProperty(self._data[0] & 0x1F)
110
+
111
+ @packet_property.setter
112
+ def packet_property(self, value: PacketProperty) -> None:
113
+ """
114
+ Set packet property type / 设置数据包属性类型。
115
+
116
+ C#: Property { set { RawData[0] = (byte)((RawData[0] & 0xE0) | (byte)value); } }
117
+ """
118
+ self._data[0] = (self._data[0] & 0xE0) | (value & 0x1F)
119
+
120
+ @property
121
+ def connection_number(self) -> int:
122
+ """
123
+ Get connection number (0-3) / 获取连接编号(0-3)。
124
+
125
+ C#: ConnectionNumber { get { return (byte)((RawData[0] & 0x60) >> 5); } }
126
+ """
127
+ return (self._data[0] & 0x60) >> 5
128
+
129
+ @connection_number.setter
130
+ def connection_number(self, value: int) -> None:
131
+ """
132
+ Set connection number (0-3) / 设置连接编号(0-3)。
133
+
134
+ C#: ConnectionNumber { set { RawData[0] = (byte) ((RawData[0] & 0x9F) | (value << 5)); } }
135
+ """
136
+ self._data[0] = (self._data[0] & 0x9F) | ((value & 0x03) << 5)
137
+
138
+ @property
139
+ def sequence(self) -> int:
140
+ """
141
+ Get sequence number (ushort, little-endian) / 获取序列号(ushort,小端序)。
142
+
143
+ C#: Sequence { get { return BitConverter.ToUInt16(RawData, 1); } }
144
+ """
145
+ return (self._data[1] & 0xFF) | ((self._data[2] & 0xFF) << 8)
146
+
147
+ @sequence.setter
148
+ def sequence(self, value: int) -> None:
149
+ """
150
+ Set sequence number (ushort, little-endian) / 设置序列号(ushort,小端序)。
151
+
152
+ Value is automatically masked to ushort range (0-65535) to handle wraparound.
153
+ 值会自动被屏蔽到 ushort 范围(0-65535)以处理回绕。
154
+
155
+ C#: Sequence { set { FastBitConverter.GetBytes(RawData, 1, value); } }
156
+ """
157
+ # Mask to ushort range to handle wraparound (C# implicitly does this)
158
+ value = value & 0xFFFF
159
+ FastBitConverter.get_bytes_ushort(self._data, 1, value)
160
+
161
+ @property
162
+ def is_fragmented(self) -> bool:
163
+ """
164
+ Check if packet is fragmented / 检查数据包是否分片。
165
+
166
+ C#: IsFragmented { get { return (RawData[0] & 0x80) != 0; } }
167
+ """
168
+ return (self._data[0] & 0x80) != 0
169
+
170
+ def mark_fragmented(self) -> None:
171
+ """
172
+ Mark packet as fragmented / 标记数据包为分片。
173
+
174
+ C#: MarkFragmented() { RawData[0] |= 0x80; }
175
+ """
176
+ self._data[0] |= 0x80
177
+
178
+ @property
179
+ def channel_id(self) -> int:
180
+ """
181
+ Get channel ID / 获取通道 ID。
182
+
183
+ C#: ChannelId { get { return RawData[3]; } }
184
+ """
185
+ return self._data[3]
186
+
187
+ @channel_id.setter
188
+ def channel_id(self, value: int) -> None:
189
+ """
190
+ Set channel ID / 设置通道 ID。
191
+
192
+ C#: ChannelId { set { RawData[3] = value; } }
193
+ """
194
+ self._data[3] = value & 0xFF
195
+
196
+ @property
197
+ def fragment_id(self) -> int:
198
+ """
199
+ Get fragment ID (ushort, little-endian, at offset 4) / 获取分片 ID。
200
+
201
+ C#: FragmentId { get { return BitConverter.ToUInt16(RawData, 4); } }
202
+ """
203
+ return (self._data[4] & 0xFF) | ((self._data[5] & 0xFF) << 8)
204
+
205
+ @fragment_id.setter
206
+ def fragment_id(self, value: int) -> None:
207
+ """
208
+ Set fragment ID (ushort, little-endian, at offset 4) / 设置分片 ID。
209
+
210
+ Auto-expands buffer if needed for fragmentation attributes.
211
+ 如果需要,自动扩展缓冲区以容纳分片属性。
212
+
213
+ C#: FragmentId { set { FastBitConverter.GetBytes(RawData, 4, value); } }
214
+ """
215
+ # Ensure buffer is large enough for fragmentation data
216
+ min_size = 10 # 4 (channeled header) + 6 (fragment header)
217
+ if len(self._data) < min_size:
218
+ # Expand buffer to accommodate fragmentation
219
+ new_data = bytearray(min_size)
220
+ new_data[:len(self._data)] = self._data
221
+ self._data = new_data
222
+ self._size = max(self._size, min_size)
223
+ FastBitConverter.get_bytes_ushort(self._data, 4, value)
224
+
225
+ @property
226
+ def fragment_part(self) -> int:
227
+ """
228
+ Get fragment part number (ushort, little-endian, at offset 6) / 获取分片部分编号。
229
+
230
+ C#: FragmentPart { get { return BitConverter.ToUInt16(RawData, 6); } }
231
+ """
232
+ return (self._data[6] & 0xFF) | ((self._data[7] & 0xFF) << 8)
233
+
234
+ @fragment_part.setter
235
+ def fragment_part(self, value: int) -> None:
236
+ """
237
+ Set fragment part number (ushort, little-endian, at offset 6) / 设置分片部分编号。
238
+
239
+ Auto-expands buffer if needed for fragmentation attributes.
240
+ 如果需要,自动扩展缓冲区以容纳分片属性。
241
+
242
+ C#: FragmentPart { set { FastBitConverter.GetBytes(RawData, 6, value); } }
243
+ """
244
+ # Ensure buffer is large enough for fragmentation data
245
+ min_size = 10 # 4 (channeled header) + 6 (fragment header)
246
+ if len(self._data) < min_size:
247
+ # Expand buffer to accommodate fragmentation
248
+ new_data = bytearray(min_size)
249
+ new_data[:len(self._data)] = self._data
250
+ self._data = new_data
251
+ self._size = max(self._size, min_size)
252
+ FastBitConverter.get_bytes_ushort(self._data, 6, value)
253
+
254
+ @property
255
+ def fragments_total(self) -> int:
256
+ """
257
+ Get total number of fragments (ushort, little-endian, at offset 8) / 获取分片总数。
258
+
259
+ C#: FragmentsTotal { get { return BitConverter.ToUInt16(RawData, 8); } }
260
+ """
261
+ return (self._data[8] & 0xFF) | ((self._data[9] & 0xFF) << 8)
262
+
263
+ @fragments_total.setter
264
+ def fragments_total(self, value: int) -> None:
265
+ """
266
+ Set total number of fragments (ushort, little-endian, at offset 8) / 设置分片总数。
267
+
268
+ Auto-expands buffer if needed for fragmentation attributes.
269
+ 如果需要,自动扩展缓冲区以容纳分片属性。
270
+
271
+ C#: FragmentsTotal { set { FastBitConverter.GetBytes(RawData, 8, value); } }
272
+ """
273
+ # Ensure buffer is large enough for fragmentation data
274
+ min_size = 10 # 4 (channeled header) + 6 (fragment header)
275
+ if len(self._data) < min_size:
276
+ # Expand buffer to accommodate fragmentation
277
+ new_data = bytearray(min_size)
278
+ new_data[:len(self._data)] = self._data
279
+ self._data = new_data
280
+ self._size = max(self._size, min_size)
281
+ FastBitConverter.get_bytes_ushort(self._data, 8, value)
282
+
283
+ @property
284
+ def raw_data(self) -> memoryview:
285
+ """
286
+ Get raw packet data as memoryview for efficient access / 获取原始数据包数据。
287
+
288
+ C#: RawData (public byte[])
289
+ """
290
+ return memoryview(self._data)[:self._size]
291
+
292
+ @property
293
+ def size(self) -> int:
294
+ """
295
+ Get packet size in bytes / 获取数据包大小(字节)。
296
+
297
+ C#: Size (public int)
298
+ """
299
+ return self._size
300
+
301
+ @size.setter
302
+ def size(self, value: int) -> None:
303
+ """
304
+ Set packet size / 设置数据包大小。
305
+
306
+ C#: Size (can be set to truncate packet)
307
+ """
308
+ self._size = min(value, len(self._data))
309
+
310
+ @property
311
+ def user_data(self) -> Optional[object]:
312
+ """
313
+ Get user-defined data attached to this packet / 获取附加到此数据包的用户定义数据。
314
+
315
+ C#: UserData (public object)
316
+ """
317
+ return self._user_data
318
+
319
+ @user_data.setter
320
+ def user_data(self, value: Optional[object]) -> None:
321
+ """
322
+ Set user-defined data attached to this packet / 设置附加到此数据包的用户定义数据。
323
+
324
+ C#: UserData (public object)
325
+ """
326
+ self._user_data = value
327
+
328
+ def get_header_size(self) -> int:
329
+ """
330
+ Get header size for this packet's property type / 获取此数据包属性类型的头部大小。
331
+
332
+ C#: GetHeaderSize() { return HeaderSizes[RawData[0] & 0x1F]; }
333
+
334
+ Returns:
335
+ Header size in bytes / 头部大小(字节)
336
+ """
337
+ return self._header_sizes[self.packet_property]
338
+
339
+ def get_data(self) -> bytes:
340
+ """
341
+ Get packet data (excluding header) / 获取数据包数据(不包括头部)。
342
+
343
+ Returns:
344
+ Packet payload data / 数据包负载数据
345
+ """
346
+ header_size = self.get_header_size()
347
+ return bytes(self._data[header_size:self._size])
348
+
349
+ def get_bytes(self) -> bytes:
350
+ """
351
+ Get complete packet as bytes / 获取完整数据包的字节。
352
+
353
+ Returns:
354
+ Complete packet including header / 包括头部的完整数据包
355
+ """
356
+ return bytes(self._data[:self._size])
357
+
358
+ def verify(self) -> bool:
359
+ """
360
+ Verify packet is valid / 验证数据包是否有效。
361
+
362
+ C#: Verify() implementation
363
+
364
+ Returns:
365
+ True if packet has valid structure, False otherwise.
366
+ 如果数据包结构有效则返回 True,否则返回 False。
367
+ """
368
+ prop = self._data[0] & 0x1F
369
+ if prop >= len(PacketProperty):
370
+ return False
371
+
372
+ try:
373
+ prop_enum = PacketProperty(prop)
374
+ except ValueError:
375
+ return False
376
+
377
+ header_size = self._header_sizes.get(prop_enum, NetConstants.HEADER_SIZE)
378
+ if self._size < header_size:
379
+ return False
380
+
381
+ # C#: if (fragmented || Size >= headerSize + FragmentHeaderSize)
382
+ if self.is_fragmented and self._size < header_size + NetConstants.FRAGMENT_HEADER_SIZE:
383
+ return False
384
+
385
+ return True
386
+
387
+ def __len__(self) -> int:
388
+ """Get packet size / 获取数据包大小"""
389
+ return self._size
390
+
391
+ def __bytes__(self) -> bytes:
392
+ """Convert to bytes / 转换为字节"""
393
+ return self.get_bytes()
394
+
395
+ def __repr__(self) -> str:
396
+ """String representation / 字符串表示"""
397
+ return (f"NetPacket(packet_property={self.packet_property.name}, "
398
+ f"size={self._size}, fragmented={self.is_fragmented})")
399
+
400
+
401
+ class NetPacketPool:
402
+ """
403
+ Simple object pool for NetPacket instances to reduce allocations.
404
+ NetPacket 对象池,用于减少分配。
405
+
406
+ In Python, the GC handles memory well, but pooling can still help
407
+ reduce allocation overhead for high-throughput scenarios.
408
+
409
+ 在 Python 中,GC 可以很好地处理内存,但池化仍然可以帮助
410
+ 减少高吞吐量场景的分配开销。
411
+
412
+ C# Reference: NetPacketPool.cs
413
+ """
414
+
415
+ __slots__ = ('_pool', '_max_size')
416
+
417
+ def __init__(self, max_size: int = NetConstants.PACKET_POOL_SIZE):
418
+ """
419
+ Create packet pool / 创建数据包池。
420
+
421
+ Args:
422
+ max_size: Maximum pool size / 最大池大小
423
+ """
424
+ self._pool = []
425
+ self._max_size = max_size
426
+
427
+ def get(self, size: int) -> NetPacket:
428
+ """
429
+ Get a packet from the pool or create a new one / 从池中获取或创建新数据包。
430
+
431
+ Args:
432
+ size: Required minimum size / 需要的最小大小
433
+
434
+ Returns:
435
+ NetPacket instance / NetPacket 实例
436
+ """
437
+ if self._pool:
438
+ packet = self._pool.pop()
439
+ if len(packet._data) >= size:
440
+ packet._size = size
441
+ return packet
442
+ return NetPacket(size)
443
+
444
+ def recycle(self, packet: NetPacket) -> None:
445
+ """
446
+ Return a packet to the pool for reuse / 将数据包返回到池中以供重用。
447
+
448
+ Args:
449
+ packet: Packet to recycle / 要回收的数据包
450
+ """
451
+ if len(self._pool) < self._max_size:
452
+ packet._user_data = None
453
+ self._pool.append(packet)
454
+
455
+ def clear(self) -> None:
456
+ """Clear the pool / 清空池"""
457
+ self._pool.clear()