Skip to content

Commit 49e8537

Browse files
committed
Add new helper methods for creating and accessing fake players.
1 parent 3389a1a commit 49e8537

File tree

1 file changed

+96
-0
lines changed

1 file changed

+96
-0
lines changed

src/main/java/net/darkhax/bookshelf/util/PlayerUtils.java

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,16 @@
1111
import java.util.List;
1212
import java.util.Map;
1313
import java.util.UUID;
14+
import java.util.function.BiFunction;
15+
import java.util.function.Supplier;
1416

1517
import com.mojang.authlib.GameProfile;
1618
import com.mojang.authlib.minecraft.MinecraftProfileTexture;
1719
import 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;
1924
import net.minecraft.client.Minecraft;
2025
import net.minecraft.client.entity.player.ClientPlayerEntity;
2126
import net.minecraft.client.resources.DefaultPlayerSkin;
@@ -27,8 +32,12 @@
2732
import net.minecraft.item.ItemStack;
2833
import net.minecraft.util.DamageSource;
2934
import net.minecraft.util.ResourceLocation;
35+
import net.minecraft.world.server.ServerWorld;
3036
import net.minecraftforge.api.distmarker.Dist;
3137
import 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

3342
public 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

Comments
 (0)