1111import  java .util .List ;
1212import  java .util .Map ;
1313import  java .util .UUID ;
14+ import  java .util .function .BiFunction ;
15+ import  java .util .function .Supplier ;
1416
1517import  com .mojang .authlib .GameProfile ;
1618import  com .mojang .authlib .minecraft .MinecraftProfileTexture ;
1719import  com .mojang .authlib .minecraft .MinecraftProfileTexture .Type ;
1820
21+ import  net .darkhax .bookshelf .entity .BookshelfFakePlayer ;
22+ import  net .darkhax .bookshelf .lib .function .LazyWeakReference ;
23+ import  net .darkhax .bookshelf .lib .function .NonNullSupplier ;
1924import  net .minecraft .client .Minecraft ;
2025import  net .minecraft .client .entity .player .ClientPlayerEntity ;
2126import  net .minecraft .client .resources .DefaultPlayerSkin ;
2732import  net .minecraft .item .ItemStack ;
2833import  net .minecraft .util .DamageSource ;
2934import  net .minecraft .util .ResourceLocation ;
35+ import  net .minecraft .world .server .ServerWorld ;
3036import  net .minecraftforge .api .distmarker .Dist ;
3137import  net .minecraftforge .api .distmarker .OnlyIn ;
38+ import  net .minecraftforge .common .util .FakePlayer ;
39+ import  net .minecraftforge .common .util .FakePlayerFactory ;
40+ import  net .minecraftforge .fml .common .ObfuscationReflectionHelper ;
3241
3342public  final  class  PlayerUtils  {
3443
@@ -187,4 +196,91 @@ public static ResourceLocation getPlayerTexture (GameProfile profile) {
187196        // Default to the legacy steve skin. 
188197        return  DefaultPlayerSkin .getDefaultSkin ();
189198    }
199+     
200+     /** 
201+      * Gets a fake player using their game profile. If there are no matching fake players a new 
202+      * one will be created. 
203+      *  
204+      * @param world A world instance used to load the fake player. 
205+      * @param profile The profile of the fake player to find. If there are no matches a new 
206+      *        fake player will be created with this profile. 
207+      * @return The fake player that was found or created. 
208+      */ 
209+     public  static  FakePlayer  getFakePlayer  (ServerWorld  world , GameProfile  profile ) {
210+         
211+         return  getFakePlayer (world , profile , BookshelfFakePlayer ::new );
212+     }
213+     
214+     /** 
215+      * Gets a fake player using their game profile. If there are no matching fake players a new 
216+      * one will be created using the provided factory. 
217+      *  
218+      * @param world A world instance used to load the fake player. This will be passed to the 
219+      *        factory if no matching fake players were found. 
220+      * @param profile The profile of the fake player to find. This will be passed to the 
221+      *        factory if there are no matching fake players. 
222+      * @param factory A factory used to create the fake player if a match could not be found. 
223+      * @return The fake player that was found or created. 
224+      */ 
225+     public  static  FakePlayer  getFakePlayer  (ServerWorld  world , GameProfile  profile , BiFunction <ServerWorld , GameProfile , FakePlayer > factory ) {
226+         
227+         final  Map <GameProfile , FakePlayer > fakePlayers  = getCurrentFakePlayers ();
228+         
229+         FakePlayer  fakePlayer  = fakePlayers .get (profile );
230+         
231+         if  (fakePlayer  == null ) {
232+             
233+             fakePlayer  = factory .apply (world , profile );
234+             fakePlayers .put (profile , fakePlayer );
235+         }
236+         
237+         return  fakePlayer ;
238+     }
239+     
240+     /** 
241+      * Creates a supplier that stores a weak reference to the computed fake player. The fake 
242+      * player will be recomputed as needed when the weak reference expires. 
243+      *  
244+      * @param world A world instance used to load the fake player. 
245+      * @param profile The profile of the fake player to find. If there are no matches a new 
246+      *        fake player will be created with this profile. 
247+      * @return The supplier for the fake player. 
248+      */ 
249+     public  static  Supplier <FakePlayer > getFakePlayerReference  (ServerWorld  world , GameProfile  profile ) {
250+         
251+         return  new  LazyWeakReference <>(NonNullSupplier .from ( () -> getFakePlayer (world , profile )));
252+     }
253+     
254+     /** 
255+      * Creates a supplier that stores a weak reference to the computed fake player. The fake 
256+      * player will be recomputed as needed when the weak reference expires. 
257+      *  
258+      * @param world A world instance used to load the fake player. This will be passed to the 
259+      *        factory if no matching fake players were found. 
260+      * @param profile The profile of the fake player to find. This will be passed to the 
261+      *        factory if there are no matching fake players. 
262+      * @param factory A factory used to create the fake player if a match could not be found. 
263+      * @return The supplier for the fake player. 
264+      */ 
265+     public  static  Supplier <FakePlayer > getFakePlayerReference  (ServerWorld  world , GameProfile  profile , BiFunction <ServerWorld , GameProfile , FakePlayer > factory ) {
266+         
267+         return  new  LazyWeakReference <>(NonNullSupplier .from ( () -> getFakePlayer (world , profile , factory )));
268+     }
269+     
270+     /** 
271+      * Gets Forge's internal fake player map from the FakePlayerFactory. This map only contains 
272+      * fake players that are currently loaded and can only return results when a world is 
273+      * active. 
274+      *  
275+      * Caution must be used when modifying this map as it is managed by Forge. Adding a new 
276+      * fake player should be done using 
277+      * {@link #getFakePlayer(ServerWorld, GameProfile, BiFunction)} or the FakePlayerHandler 
278+      * methods. 
279+      *  
280+      * @return The map containing all fake players that have been registered with Forge. 
281+      */ 
282+     public  static  Map <GameProfile , FakePlayer > getCurrentFakePlayers  () {
283+         
284+         return  ObfuscationReflectionHelper .getPrivateValue (FakePlayerFactory .class , null , "fakePlayers" );
285+     }
190286}
0 commit comments