@@ -102,6 +102,7 @@ static void Command()
102102 Log . info ( "/actorflags <EntityID (long)> <ActorFlags (int)> - Send specific actorflags value to entity or player" ) ;
103103 Log . info ( "/levelevent <Position (X Y Z)> <LevelEvents (int)> - Send specific level event to players" ) ;
104104 Log . info ( "/list - Spawned entities list" ) ;
105+ Log . info ( "/packet <PacketClassName> <Field1=Value1> <Field2=Value2> ... - Build and broadcast packet with custom values" ) ;
105106 Log . info ( "/pklog <enable (bool)> - Enable packet logger" ) ;
106107 Command2 ( ) ;
107108 break ;
@@ -164,6 +165,65 @@ static void Command2()
164165 case "/list" :
165166 Entitylist ( ) ;
166167 break ;
168+ case "/packet" :
169+ if ( parts . Length >= 2 )
170+ {
171+ string packetName = parts [ 1 ] ;
172+ var packetType = typeof ( Packet ) . Assembly
173+ . GetTypes ( )
174+ . FirstOrDefault ( t => t . Name . Equals ( packetName , StringComparison . OrdinalIgnoreCase ) ) ;
175+
176+ if ( packetType == null )
177+ {
178+ Log . error ( $ "Unknown packet: { packetName } ") ;
179+ break ;
180+ }
181+
182+ var packet = Activator . CreateInstance ( packetType ) ;
183+
184+ for ( int i = 2 ; i < parts . Length ; i ++ )
185+ {
186+ var arg = parts [ i ] ;
187+ var split = arg . Split ( '=' ) ;
188+ if ( split . Length != 2 )
189+ {
190+ Log . warn ( $ "Invalid arg format: { arg } . Use Field=Value.") ;
191+ continue ;
192+ }
193+
194+ var fieldName = split [ 0 ] ;
195+ var valueStr = split [ 1 ] ;
196+
197+ var prop = packetType . GetProperty ( fieldName ) ;
198+ if ( prop == null )
199+ {
200+ Log . warn ( $ "Field { fieldName } not found in { packetName } ") ;
201+ continue ;
202+ }
203+
204+ try
205+ {
206+ object value = Convert . ChangeType ( valueStr , prop . PropertyType ) ;
207+ prop . SetValue ( packet , value ) ;
208+ }
209+ catch
210+ {
211+ Log . warn ( $ "Failed to convert { valueStr } to { prop . PropertyType . Name } for { fieldName } ") ;
212+ }
213+ }
214+
215+ foreach ( var dest in Server . OnlinePlayers )
216+ {
217+ dest . Value . Send ( ( Packet ) packet ) ;
218+ }
219+
220+ Log . info ( $ "Sent { packetName } to { Server . OnlinePlayers . Count } players") ;
221+ }
222+ else
223+ {
224+ Log . info ( "Usage: /packet <PacketName> <Field1=Value1> <Field2=Value2> ..." ) ;
225+ }
226+ break ;
167227 case "/pklog" :
168228 if ( parts . Length == 2 && bool . TryParse ( parts [ 1 ] , out bool boolValue ) )
169229 {
0 commit comments