3232using System . Linq ;
3333using System . Net ;
3434using System . Numerics ;
35+ using System . Reflection ;
3536using System . Threading ;
37+ using System . Security . Cryptography ;
3638using fNbt ;
3739using log4net ;
3840using MiNET . Blocks ;
5254using MiNET . Utils . Vectors ;
5355using MiNET . Worlds ;
5456using Newtonsoft . Json ;
57+ using System . IO . Compression ;
5558
5659namespace MiNET
5760{
@@ -106,6 +109,8 @@ public class Player : Entity, IMcpeMessageHandler
106109
107110 public DamageCalculator DamageCalculator { get ; set ; } = new DamageCalculator ( ) ;
108111
112+ public TexturePackInfos PlayerPackData { get ; set ; }
113+ public Dictionary < string , string > PlayerPackMap = new Dictionary < string , string > ( ) ;
109114
110115 public Player ( MiNetServer server , IPEndPoint endPoint ) : base ( EntityType . None , null )
111116 {
@@ -171,15 +176,25 @@ public virtual void HandleMcpeResourcePackChunkRequest(McpeResourcePackChunkRequ
171176 string result = JsonConvert . SerializeObject ( message , jsonSerializerSettings ) ;
172177 Log . Debug ( $ "{ message . GetType ( ) . Name } \n { result } ") ;
173178
174- var content = File . ReadAllBytes ( @"D:\Temp\ResourcePackChunkData_8f760cf7-2ca4-44ab-ab60-9be2469b9777.zip" ) ;
179+ var content = File . ReadAllBytes ( PlayerPackMap [ message . packageId ] ) ;
180+
175181 McpeResourcePackChunkData chunkData = McpeResourcePackChunkData . CreateObject ( ) ;
176- chunkData . packageId = "5abdb963-4f3f-4d97-8482-88e2049ab149" ;
177- chunkData . chunkIndex = 0 ; // Package index ?
178- chunkData . progress = 0 ; // Long, maybe timestamp?
179- chunkData . payload = content ;
182+ chunkData . packageId = message . packageId ;
183+ chunkData . chunkIndex = message . chunkIndex ;
184+ chunkData . progress = 16384 * message . chunkIndex ;
185+ chunkData . payload = GetChunk ( content , ( int ) chunkData . chunkIndex , 16384 ) ;
180186 SendPacket ( chunkData ) ;
181187 }
182188
189+ public static byte [ ] GetChunk ( byte [ ] content , int chunkIndex , int chunkSize )
190+ {
191+ int start = chunkIndex * chunkSize ;
192+ int length = Math . Min ( chunkSize , content . Length - start ) ;
193+ byte [ ] chunk = new byte [ length ] ;
194+ Array . Copy ( content , start , chunk , 0 , length ) ;
195+ return chunk ;
196+ }
197+
183198 public virtual void HandleMcpePurchaseReceipt ( McpePurchaseReceipt message )
184199 {
185200 }
@@ -297,21 +312,32 @@ public virtual void HandleMcpeSetLocalPlayerAsInitialized(McpeSetLocalPlayerAsIn
297312 OnLocalPlayerIsInitialized ( new PlayerEventArgs ( this ) ) ;
298313 }
299314
300- private bool _serverHaveResources = false ;
315+ private bool _serverHaveResources = true ;
301316
302317 public virtual void HandleMcpeResourcePackClientResponse ( McpeResourcePackClientResponse message )
303318 {
304319 if ( Log . IsDebugEnabled ) Log . Debug ( $ "Handled packet 0x{ message . Id : X2} \n { Packet . HexDump ( message . Bytes ) } ") ;
305320
306321 if ( message . responseStatus == 2 )
307322 {
308- McpeResourcePackDataInfo dataInfo = McpeResourcePackDataInfo . CreateObject ( ) ;
309- dataInfo . packageId = "5abdb963-4f3f-4d97-8482-88e2049ab149" ;
310- dataInfo . maxChunkSize = 1048576 ;
311- dataInfo . chunkCount = 1 ;
312- dataInfo . compressedPackageSize = 359901 ; // Lenght of data
313- dataInfo . hash = new byte [ ] { 57 , 38 , 13 , 50 , 39 , 63 , 88 , 63 , 59 , 27 , 63 , 63 , 63 , 63 , 6 , 63 , 54 , 7 , 84 , 63 , 47 , 91 , 63 , 120 , 63 , 120 , 42 , 5 , 104 , 2 , 63 , 18 } ;
314- SendPacket ( dataInfo ) ;
323+ foreach ( string packid in message . resourcepackids )
324+ {
325+ var uuid = packid . Substring ( 0 , Math . Min ( packid . Length , 36 ) ) ;
326+ var content = File . ReadAllBytes ( PlayerPackMap [ uuid ] ) ;
327+
328+ SHA256 sha256 = SHA256 . Create ( ) ;
329+ byte [ ] packHash = sha256 . ComputeHash ( content ) ;
330+
331+ McpeResourcePackDataInfo dataInfo = McpeResourcePackDataInfo . CreateObject ( ) ;
332+ dataInfo . packageId = uuid ;
333+ dataInfo . maxChunkSize = 16384 ;
334+ dataInfo . chunkCount = ( uint ) Math . Ceiling ( ( double ) content . Count ( ) / 16384 ) ;
335+ dataInfo . compressedPackageSize = ( ulong ) content . Count ( ) ;
336+ dataInfo . hash = packHash ;
337+ dataInfo . isPremium = false ;
338+ dataInfo . packType = 6 ;
339+ SendPacket ( dataInfo ) ;
340+ }
315341 return ;
316342 }
317343 else if ( message . responseStatus == 3 )
@@ -332,6 +358,8 @@ public virtual void HandleMcpeResourcePackClientResponse(McpeResourcePackClientR
332358 {
333359 MiNetServer . FastThreadPool . QueueUserWorkItem ( ( ) => { Start ( null ) ; } ) ;
334360 }
361+ PlayerPackData . Clear ( ) ;
362+ PlayerPackMap . Clear ( ) ;
335363 return ;
336364 }
337365 }
@@ -341,18 +369,45 @@ public virtual void SendResourcePacksInfo()
341369 McpeResourcePacksInfo packInfo = McpeResourcePacksInfo . CreateObject ( ) ;
342370 if ( _serverHaveResources )
343371 {
344- packInfo . mustAccept = false ;
345- packInfo . behahaviorpackinfos = new ResourcePackInfos
372+ var packInfos = new TexturePackInfos ( ) ;
373+ var directory = Config . GetProperty ( "ResourceDirectory" , Path . GetDirectoryName ( new Uri ( Assembly . GetEntryAssembly ( ) . Location ) . LocalPath ) ) ;
374+ packInfo . mustAccept = Config . GetProperty ( "ForceResourcePacks" , false ) ;
375+
376+ foreach ( var zipPack in Directory . GetFiles ( directory , "*.zip" ) )
346377 {
347- new ResourcePackInfo ( )
378+ var archive = ZipFile . OpenRead ( zipPack ) ;
379+ var packDir = archive . Entries [ 0 ] . FullName . Substring ( 0 , archive . Entries [ 0 ] . FullName . IndexOf ( '/' ) ) ;
380+
381+ if ( packDir == null )
348382 {
349- UUID = "5abdb963-4f3f-4d97-8482-88e2049ab149" ,
350- Version = "0.0.1" ,
351- Size = 359901
352- } ,
353- } ;
354- }
383+ Log . Error ( $ "Invalid resource pack { zipPack } . Wrong folder structure") ;
384+ continue ;
385+ }
386+
387+ var entry = archive . GetEntry ( $ "{ packDir } /manifest.json") ;
355388
389+ if ( entry == null )
390+ {
391+ Log . Error ( $ "Invalid resource pack { packDir } . Unable to locate manifest.json") ;
392+ continue ;
393+ }
394+
395+ using ( var stream = entry . Open ( ) )
396+ using ( var reader = new StreamReader ( stream ) )
397+ {
398+ string jsonContent = reader . ReadToEnd ( ) ;
399+ manifestStructure obj = JsonConvert . DeserializeObject < manifestStructure > ( jsonContent ) ;
400+ packInfos . Add ( new TexturePackInfo {
401+ UUID = obj . Header . Uuid ,
402+ Version = $ "{ obj . Header . Version [ 0 ] } .{ obj . Header . Version [ 1 ] } .{ obj . Header . Version [ 2 ] } ",
403+ Size = ( ulong ) File . ReadAllBytes ( zipPack ) . Count ( ) ,
404+ } ) ;
405+ PlayerPackMap . Add ( obj . Header . Uuid , zipPack ) ;
406+ }
407+ }
408+ PlayerPackData = packInfos ;
409+ packInfo . texturepacks = packInfos ;
410+ }
356411 SendPacket ( packInfo ) ;
357412 }
358413
@@ -363,15 +418,13 @@ public virtual void SendResourcePackStack()
363418
364419 if ( _serverHaveResources )
365420 {
366- packStack . mustAccept = false ;
367- packStack . resourcepackidversions = new ResourcePackIdVersions
421+ packStack . mustAccept = Config . GetProperty ( "ForceResourcePacks" , false ) ;
422+ var packVersions = new ResourcePackIdVersions ( ) ;
423+ foreach ( var packData in PlayerPackData )
368424 {
369- new PackIdVersion ( )
370- {
371- Id = "5abdb963-4f3f-4d97-8482-88e2049ab149" ,
372- Version = "0.0.1"
373- } ,
374- } ;
425+ packVersions . Add ( new PackIdVersion { Id = packData . UUID , Version = packData . Version } ) ;
426+ }
427+ packStack . resourcepackidversions = packVersions ;
375428 }
376429
377430 SendPacket ( packStack ) ;
0 commit comments