mirror of
https://github.com/tanyaofei/minecraft-fakeplayer.git
synced 2025-09-14 11:16:46 +08:00
优化代码
This commit is contained in:
parent
35ef7644b9
commit
0651bb0171
@ -3,7 +3,7 @@ package io.github.hello09x.fakeplayer;
|
||||
import io.github.hello09x.fakeplayer.command.FakePlayerCommand;
|
||||
import io.github.hello09x.fakeplayer.listener.PlayerDeathListener;
|
||||
import io.github.hello09x.fakeplayer.listener.PlayerQuitListener;
|
||||
import io.github.hello09x.fakeplayer.listener.PlayerTeleportListener;
|
||||
import io.github.hello09x.fakeplayer.manager.FakePlayerManager;
|
||||
import lombok.Getter;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
@ -22,15 +22,14 @@ public final class Main extends JavaPlugin {
|
||||
}
|
||||
|
||||
{
|
||||
// getServer().getPluginManager().registerEvents(PlayerQuitListener.instance, Main.getInstance());
|
||||
getServer().getPluginManager().registerEvents(PlayerQuitListener.instance, Main.getInstance());
|
||||
getServer().getPluginManager().registerEvents(PlayerDeathListener.instance, Main.getInstance());
|
||||
// getServer().getPluginManager().registerEvents(PlayerTeleportListener.instance, Main.getInstance());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
// Plugin shutdown logic
|
||||
FakePlayerManager.instance.removeFakePlayers();
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import net.kyori.adventure.sound.Sound;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.player.PlayerTeleportEvent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@ -90,18 +91,7 @@ public abstract class AbstractTeleportCommand extends ExecutableCommand {
|
||||
}
|
||||
|
||||
protected void teleport(@NotNull Player from, @NotNull Player to) {
|
||||
from.teleport(to.getLocation());
|
||||
from.playSound(Sound.sound(
|
||||
ENTITY_ENDERMAN_TELEPORT.key(),
|
||||
Sound.Source.PLAYER,
|
||||
1.0F,
|
||||
1.0F
|
||||
));
|
||||
to.playSound(Sound.sound(
|
||||
ENTITY_ENDERMAN_TELEPORT.key(),
|
||||
Sound.Source.PLAYER,
|
||||
1.0F,
|
||||
1.0F
|
||||
));
|
||||
from.teleport(to.getLocation(), PlayerTeleportEvent.TeleportCause.COMMAND);
|
||||
to.getLocation().getWorld().playSound(to.getLocation(), ENTITY_ENDERMAN_TELEPORT, 1.0F, 1.0F);
|
||||
}
|
||||
}
|
||||
|
@ -91,8 +91,7 @@ public class RemoveCommand extends ExecutableCommand {
|
||||
return fakes
|
||||
.stream()
|
||||
.map(Player::getName)
|
||||
.filter(name -> args[0].isBlank()
|
||||
|| name.toLowerCase().contains(args[0].toLowerCase()))
|
||||
.filter(name -> args[0].isBlank() || name.toLowerCase().contains(args[0].toLowerCase()))
|
||||
.toList();
|
||||
}
|
||||
}
|
||||
|
@ -46,11 +46,6 @@ public class TpHereCommand extends AbstractTeleportCommand {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!fake.getWorld().equals(creator.getWorld())) {
|
||||
sender.sendMessage(text("暂不支持跨世界传送...", RED));
|
||||
return true;
|
||||
}
|
||||
|
||||
teleport(fake, creator);
|
||||
return true;
|
||||
}
|
||||
|
@ -0,0 +1,67 @@
|
||||
package io.github.hello09x.fakeplayer.core;
|
||||
|
||||
import com.mojang.datafixers.DataFixer;
|
||||
import io.github.hello09x.fakeplayer.util.ReflectionUtils;
|
||||
import net.minecraft.advancements.Advancement;
|
||||
import net.minecraft.advancements.AdvancementProgress;
|
||||
import net.minecraft.server.PlayerAdvancements;
|
||||
import net.minecraft.server.ServerAdvancementManager;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.server.players.PlayerList;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Map;
|
||||
|
||||
public class EmptyAdvancements extends PlayerAdvancements {
|
||||
|
||||
public final static Field PROGRESS = ReflectionUtils.getFirstFieldByType(PlayerAdvancements.class, Map.class, false);
|
||||
|
||||
public EmptyAdvancements(
|
||||
DataFixer datafixer,
|
||||
PlayerList playerlist,
|
||||
ServerAdvancementManager manager,
|
||||
Path path,
|
||||
ServerPlayer player
|
||||
) {
|
||||
super(datafixer, playerlist, manager, path, player);
|
||||
this.save();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean award(Advancement advancement, String s) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flushDirty(ServerPlayer player) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AdvancementProgress getOrStartProgress(Advancement advancement) {
|
||||
return new AdvancementProgress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean revoke(Advancement advancement, String s) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayer(ServerPlayer player) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelectedTab(Advancement advancement) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopListening() {
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -2,12 +2,16 @@ package io.github.hello09x.fakeplayer.entity;
|
||||
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import io.github.hello09x.fakeplayer.Main;
|
||||
import io.github.hello09x.fakeplayer.core.EmptyAdvancements;
|
||||
import io.github.hello09x.fakeplayer.core.EmptyConnection;
|
||||
import io.github.hello09x.fakeplayer.core.EmptyNetworkManager;
|
||||
import io.github.hello09x.fakeplayer.util.ReflectionUtils;
|
||||
import lombok.Getter;
|
||||
import net.minecraft.network.protocol.PacketFlow;
|
||||
import net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket;
|
||||
import net.minecraft.network.protocol.game.ServerboundClientInformationPacket;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.PlayerAdvancements;
|
||||
import net.minecraft.server.level.ChunkMap;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
@ -15,6 +19,7 @@ import net.minecraft.world.entity.HumanoidArm;
|
||||
import net.minecraft.world.entity.player.ChatVisiblity;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.craftbukkit.v1_20_R1.CraftServer;
|
||||
import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity;
|
||||
import org.bukkit.craftbukkit.v1_20_R1.entity.CraftPlayer;
|
||||
@ -22,31 +27,33 @@ import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||
import org.bukkit.event.player.PlayerRespawnEvent;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.bukkit.Sound.ENTITY_ENDERMAN_TELEPORT;
|
||||
|
||||
public class FakePlayer extends ServerPlayer {
|
||||
|
||||
private final UUID uniqueId;
|
||||
public final static Field advancements = ReflectionUtils.getFirstFieldByType(ServerPlayer.class, PlayerAdvancements.class, false);
|
||||
|
||||
private final String name;
|
||||
|
||||
private final Location spawnLocation;
|
||||
@Getter
|
||||
private @NotNull
|
||||
final Location spawnLocation;
|
||||
|
||||
public FakePlayer(
|
||||
MinecraftServer server,
|
||||
ServerLevel world,
|
||||
UUID uniqueId,
|
||||
String name,
|
||||
Location at
|
||||
@NotNull MinecraftServer server,
|
||||
@NotNull ServerLevel world,
|
||||
@NotNull UUID uniqueId,
|
||||
@NotNull String name,
|
||||
@NotNull Location at
|
||||
) {
|
||||
super(server, world, new GameProfile(uniqueId, name));
|
||||
this.uniqueId = uniqueId;
|
||||
this.name = name;
|
||||
this.spawnLocation = at;
|
||||
|
||||
try {
|
||||
@ -56,9 +63,25 @@ public class FakePlayer extends ServerPlayer {
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
if (advancements != null) {
|
||||
try {
|
||||
advancements.set(
|
||||
this,
|
||||
new EmptyAdvancements(
|
||||
server.getFixerUpper(),
|
||||
server.getPlayerList(),
|
||||
server.getAdvancements(),
|
||||
Main.getInstance().getDataFolder().getParentFile().toPath(),
|
||||
this
|
||||
));
|
||||
} catch (IllegalAccessException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static boolean isChunkLoaded(Location at) {
|
||||
private static boolean isChunkLoaded(@NotNull Location at) {
|
||||
if (at.getWorld() == null) {
|
||||
return false;
|
||||
}
|
||||
@ -67,17 +90,21 @@ public class FakePlayer extends ServerPlayer {
|
||||
return at.getWorld().isChunkLoaded(x, z);
|
||||
}
|
||||
|
||||
public Player prepare() {
|
||||
addToPlayerList();
|
||||
spawn();
|
||||
public @NotNull Player spawn() {
|
||||
this.boardcast();
|
||||
this.addEntityToWorld();
|
||||
|
||||
var p = Objects.requireNonNull(Bukkit.getPlayer(this.uuid));
|
||||
p.setSleepingIgnored(true);
|
||||
p.setPersistent(false);
|
||||
p.setInvulnerable(true);
|
||||
|
||||
new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!p.isOnline()) {
|
||||
cancel();
|
||||
}
|
||||
doTick();
|
||||
tickCount++;
|
||||
}
|
||||
@ -86,9 +113,9 @@ public class FakePlayer extends ServerPlayer {
|
||||
}
|
||||
|
||||
@SuppressWarnings("all")
|
||||
public void addToPlayerList() {
|
||||
var packet = new ServerboundClientInformationPacket(
|
||||
"EN",
|
||||
public void boardcast() {
|
||||
this.updateOptions(new ServerboundClientInformationPacket(
|
||||
"en_us",
|
||||
10,
|
||||
ChatVisiblity.FULL,
|
||||
false,
|
||||
@ -96,14 +123,14 @@ public class FakePlayer extends ServerPlayer {
|
||||
HumanoidArm.LEFT,
|
||||
false,
|
||||
true
|
||||
);
|
||||
this.updateOptions(packet);
|
||||
));
|
||||
|
||||
var entity = this.getBukkitEntity();
|
||||
var handle = (ServerPlayer) ((CraftEntity) entity).getHandle();
|
||||
if (handle.level() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
var playerList = handle.level().players();
|
||||
if (!playerList.contains(handle)) {
|
||||
((List) playerList).add(handle);
|
||||
@ -132,15 +159,15 @@ public class FakePlayer extends ServerPlayer {
|
||||
|
||||
}
|
||||
|
||||
public void spawn() {
|
||||
public void addEntityToWorld() {
|
||||
var entity = this.getBukkitEntity();
|
||||
var handle = (ServerPlayer) ((CraftEntity) entity).getHandle();
|
||||
|
||||
if (!isChunkLoaded(spawnLocation)) {
|
||||
spawnLocation.getChunk().load();
|
||||
}
|
||||
handle.level().addFreshEntity(handle, CreatureSpawnEvent.SpawnReason.CUSTOM);
|
||||
|
||||
handle.level().addFreshEntity(handle, CreatureSpawnEvent.SpawnReason.CUSTOM);
|
||||
((CraftServer) Bukkit.getServer()).getHandle().respawn(
|
||||
this,
|
||||
true,
|
||||
@ -149,6 +176,7 @@ public class FakePlayer extends ServerPlayer {
|
||||
|
||||
// move directly
|
||||
getBukkitEntity().teleport(spawnLocation);
|
||||
spawnLocation.getWorld().playSound(spawnLocation, Sound.ENTITY_ENDERMAN_TELEPORT, 1.0F, 1.0F);
|
||||
}
|
||||
|
||||
|
||||
|
@ -19,6 +19,7 @@ public class PlayerDeathListener implements Listener {
|
||||
return;
|
||||
}
|
||||
|
||||
// 假人不会复活, 死掉了就踢掉
|
||||
player.kick();
|
||||
}
|
||||
|
||||
|
@ -1,35 +0,0 @@
|
||||
package io.github.hello09x.fakeplayer.listener;
|
||||
|
||||
import io.github.hello09x.fakeplayer.manager.FakePlayerManager;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerTeleportEvent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class PlayerTeleportListener implements Listener {
|
||||
|
||||
public final static PlayerTeleportListener instance = new PlayerTeleportListener();
|
||||
private final FakePlayerManager manager = FakePlayerManager.instance;
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST)
|
||||
public void handlePlayerTeleport(@NotNull PlayerTeleportEvent event) {
|
||||
if (!manager.isFakePlayer(event.getPlayer())) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 创建玩家时会使用这个传送原因
|
||||
if (event.getCause() == PlayerTeleportEvent.TeleportCause.SPECTATE) {
|
||||
return;
|
||||
}
|
||||
|
||||
var from = event.getFrom().getWorld().getUID();
|
||||
var to = event.getTo().getWorld().getUID();
|
||||
if (from.equals(to)) {
|
||||
return;
|
||||
}
|
||||
|
||||
event.setCancelled(true);
|
||||
}
|
||||
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
package io.github.hello09x.fakeplayer.manager;
|
||||
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import io.github.hello09x.fakeplayer.Main;
|
||||
import io.github.hello09x.fakeplayer.entity.FakePlayer;
|
||||
import org.bukkit.Bukkit;
|
||||
@ -25,8 +24,16 @@ public class FakePlayerManager {
|
||||
|
||||
public final static FakePlayerManager instance = new FakePlayerManager();
|
||||
|
||||
private final static String META_KEY_CREATOR = "fakeplayer:creator";
|
||||
|
||||
private final FakeplayerProperties properties = FakeplayerProperties.instance;
|
||||
|
||||
/**
|
||||
* 创建一个假人
|
||||
*
|
||||
* @param creator 创建者
|
||||
* @param at 生成地点
|
||||
*/
|
||||
public synchronized void spawnFakePlayer(
|
||||
@NotNull CommandSender creator,
|
||||
@NotNull Location at
|
||||
@ -50,9 +57,8 @@ public class FakePlayerManager {
|
||||
UUID.randomUUID(),
|
||||
name,
|
||||
at
|
||||
);
|
||||
var p = player.prepare();
|
||||
p.setMetadata(FakePlayerSpawner.META_KEY_CREATOR, new FixedMetadataValue(Main.getInstance(), creator.getName()));
|
||||
).spawn();
|
||||
player.setMetadata(META_KEY_CREATOR, new FixedMetadataValue(Main.getInstance(), creator.getName()));
|
||||
}
|
||||
|
||||
public @Nullable Player getFakePlayer(@NotNull CommandSender creator, @NotNull String name) {
|
||||
@ -69,6 +75,12 @@ public class FakePlayerManager {
|
||||
return fake;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据名称获取假人
|
||||
*
|
||||
* @param name 名称
|
||||
* @return 假人
|
||||
*/
|
||||
public @Nullable Player getFakePlayer(@NotNull String name) {
|
||||
var player = Bukkit.getServer().getPlayer(name);
|
||||
if (player == null) {
|
||||
@ -82,6 +94,12 @@ public class FakePlayerManager {
|
||||
return player;
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除指定创建者创建的假人
|
||||
*
|
||||
* @param creator 创建者
|
||||
* @return 移除假人的数量
|
||||
*/
|
||||
public int removeFakePlayers(@NotNull Player creator) {
|
||||
var fakes = getFakePlayers(creator);
|
||||
for (var f : fakes) {
|
||||
@ -90,8 +108,14 @@ public class FakePlayerManager {
|
||||
return fakes.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取一个假人的创建者, 如果这个玩家不是假人, 则为 {@code null}
|
||||
*
|
||||
* @param fakePlayer 假人
|
||||
* @return 假人的创建者
|
||||
*/
|
||||
public @Nullable String getCreator(@NotNull Player fakePlayer) {
|
||||
var meta = fakePlayer.getMetadata(FakePlayerSpawner.META_KEY_CREATOR);
|
||||
var meta = fakePlayer.getMetadata(META_KEY_CREATOR);
|
||||
if (meta.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
@ -99,6 +123,11 @@ public class FakePlayerManager {
|
||||
return meta.get(0).asString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除所有假人
|
||||
*
|
||||
* @return 移除的假人数量
|
||||
*/
|
||||
public int removeFakePlayers() {
|
||||
var fakes = getFakePlayers();
|
||||
for (var f : fakes) {
|
||||
@ -107,29 +136,44 @@ public class FakePlayerManager {
|
||||
return fakes.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return 获取所有假人
|
||||
*/
|
||||
public @NotNull List<Player> getFakePlayers() {
|
||||
return Bukkit
|
||||
.getServer()
|
||||
.getOnlinePlayers()
|
||||
.stream()
|
||||
.filter(p -> !p.getMetadata(FakePlayerSpawner.META_KEY_CREATOR).isEmpty())
|
||||
.filter(p -> !p.getMetadata(META_KEY_CREATOR).isEmpty())
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取创建者创建的所有假人
|
||||
*
|
||||
* @param creator 创建者
|
||||
* @return 创建者创建的假人
|
||||
*/
|
||||
public @NotNull List<Player> getFakePlayers(@NotNull CommandSender creator) {
|
||||
var name = creator.getName();
|
||||
return Bukkit
|
||||
.getServer()
|
||||
.getOnlinePlayers()
|
||||
.stream()
|
||||
.filter(p -> p.getMetadata(FakePlayerSpawner.META_KEY_CREATOR)
|
||||
.filter(p -> p.getMetadata(META_KEY_CREATOR)
|
||||
.stream()
|
||||
.anyMatch(meta -> meta.asString().equals(name)))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断一名玩家是否是假人
|
||||
*
|
||||
* @param player 玩家
|
||||
* @return 是否是假人
|
||||
*/
|
||||
public boolean isFakePlayer(@NotNull Player player) {
|
||||
return !player.getMetadata(FakePlayerSpawner.META_KEY_CREATOR).isEmpty();
|
||||
return !player.getMetadata(META_KEY_CREATOR).isEmpty();
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,99 +0,0 @@
|
||||
package io.github.hello09x.fakeplayer.manager;
|
||||
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import io.github.hello09x.fakeplayer.Main;
|
||||
import io.github.hello09x.fakeplayer.core.EmptyNetworkManager;
|
||||
import net.kyori.adventure.sound.Sound;
|
||||
import net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.craftbukkit.v1_20_R1.CraftServer;
|
||||
import org.bukkit.craftbukkit.v1_20_R1.CraftWorld;
|
||||
import org.bukkit.craftbukkit.v1_20_R1.entity.CraftPlayer;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.player.PlayerRespawnEvent;
|
||||
import org.bukkit.event.player.PlayerTeleportEvent;
|
||||
import org.bukkit.metadata.FixedMetadataValue;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import static org.bukkit.Sound.ENTITY_ENDERMAN_TELEPORT;
|
||||
|
||||
public class FakePlayerSpawner {
|
||||
|
||||
public final static String META_KEY_CREATOR = "fakeplayer::creator";
|
||||
|
||||
// public static @NotNull Player spawn(
|
||||
// @NotNull UUID uniqueId,
|
||||
// @NotNull String name,
|
||||
// @NotNull Player creator,
|
||||
// @NotNull Location at
|
||||
// ) {
|
||||
// var craftServer = (CraftServer) Bukkit.getServer();
|
||||
// var server = craftServer.getServer();
|
||||
// var gameProfile = new GameProfile(uniqueId, name);
|
||||
// var world = ((CraftWorld) at.getWorld()).getHandle();
|
||||
//
|
||||
// var entityPlayer = new EntityPlayer(server, world, gameProfile);
|
||||
// var craftPlayer = entityPlayer.getBukkitEntity();
|
||||
//
|
||||
//
|
||||
// entityPlayer.f = 0; // ping
|
||||
// entityPlayer.c = new PlayerConnection(
|
||||
// server,
|
||||
// new EmptyNetworkManager(EnumProtocolDirection.a),
|
||||
// entityPlayer
|
||||
// );
|
||||
//
|
||||
// craftPlayer.setFirstPlayed(System.currentTimeMillis());
|
||||
// craftServer.getHandle().respawn(
|
||||
// entityPlayer,
|
||||
// true,
|
||||
// PlayerRespawnEvent.RespawnReason.PLUGIN
|
||||
// );
|
||||
// refreshTabList(entityPlayer);
|
||||
//
|
||||
// var holder = Objects.requireNonNull(Bukkit.getPlayer(uniqueId));
|
||||
// holder.setViewDistance(9);
|
||||
// holder.setAffectsSpawning(true);
|
||||
// holder.setSleepingIgnored(true);
|
||||
// holder.setPersistent(false);
|
||||
// holder.setGameMode(GameMode.CREATIVE);
|
||||
// holder.setAllowFlight(true);
|
||||
// holder.setMetadata(META_KEY_CREATOR, new FixedMetadataValue(Main.getInstance(), creator.getUniqueId().toString()));
|
||||
// holder.teleport(at, PlayerTeleportEvent.TeleportCause.SPECTATE);
|
||||
// creator.playSound(Sound.sound(
|
||||
// ENTITY_ENDERMAN_TELEPORT.key(),
|
||||
// Sound.Source.PLAYER,
|
||||
// 1.0F,
|
||||
// 1.0F
|
||||
// ));
|
||||
//
|
||||
// CompletableFuture.runAsync(() -> {
|
||||
// System.out.println(holder);
|
||||
// System.out.println(craftPlayer);
|
||||
// });
|
||||
// return holder;
|
||||
// }
|
||||
//
|
||||
// private static void refreshTabList(EntityPlayer player) {
|
||||
// try {
|
||||
// var field = EntityPlayer.class.getDeclaredField("cU");
|
||||
// field.setAccessible(true);
|
||||
// field.set(player, true);
|
||||
// } catch (NoSuchFieldException | IllegalAccessException e) {
|
||||
// throw new RuntimeException(e);
|
||||
// }
|
||||
//
|
||||
// for (var online : Bukkit.getOnlinePlayers()) {
|
||||
// ((CraftPlayer) online).getHandle().c.a(new ClientboundPlayerInfoUpdatePacket(ClientboundPlayerInfoUpdatePacket.a.a, player)); //ADD_PLAYER
|
||||
// ((CraftPlayer) online).getHandle().c.a(new ClientboundPlayerInfoUpdatePacket(ClientboundPlayerInfoUpdatePacket.a.d, player)); //UPDATE_LISTED
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package io.github.hello09x.fakeplayer.util;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
public class ReflectionUtils {
|
||||
|
||||
private final static MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
|
||||
|
||||
public static @Nullable Field getFirstFieldByType(Class<?> clazz, Class<?> fieldType, boolean includeStatic) {
|
||||
for (var field : clazz.getDeclaredFields()) {
|
||||
if (includeStatic ^ Modifier.isStatic(field.getModifiers())) {
|
||||
continue;
|
||||
}
|
||||
if (field.getType() == fieldType) {
|
||||
field.setAccessible(true);
|
||||
return field;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
@ -12,6 +12,9 @@ commands:
|
||||
|
||||
permissions:
|
||||
fakeplayer:
|
||||
default: true
|
||||
fakeplayer.admin:
|
||||
description: '假人基础权限'
|
||||
default: op
|
||||
|
||||
fakeplayer.admin:
|
||||
description: '假人管理员权限'
|
||||
default: op
|
||||
|
Loading…
Reference in New Issue
Block a user