mirror of
https://github.com/tanyaofei/minecraft-fakeplayer.git
synced 2025-09-14 11:16:46 +08:00
优化代码
This commit is contained in:
parent
70da43b128
commit
7235afecac
44
README.md
44
README.md
@ -13,28 +13,28 @@
|
||||
|
||||
## 命令
|
||||
|
||||
+ /fp ? - 查看帮助手册
|
||||
+ /fp reload - 重载配置文件
|
||||
+ /fp create - 创建一个假人
|
||||
+ /fp kill - 移除假人
|
||||
+ /fp tp - 传送到假人身边
|
||||
+ /fp tps - 与假人交换位置
|
||||
+ /fp tphere - 将假人传送到自己身边
|
||||
+ /fp health - 查看假人的生命值
|
||||
+ /fp exp - 查看假人的经验值
|
||||
+ /fp expme - 转移假人的经验值
|
||||
+ /fp config - 玩家个性化配置
|
||||
+ /fp config set - 设置个性化配置
|
||||
+ /fp config get - 查看个性化配置
|
||||
+ /fp drop - 丢弃手上物品
|
||||
+ /fp dropinv - 丢弃背包物品
|
||||
+ /fp look - 让假人看向指定位置
|
||||
+ /fp move - 让假人移动
|
||||
+ /fp turn - 让假人转身
|
||||
+ /fp jump - 让假人跳跃
|
||||
+ /fp attack - 让假人点击鼠标左键 **(实验性)**
|
||||
+ /fp use - 让假人点击鼠标右键 **(实验性)**
|
||||
+ /fp cmd - 让假人执行他有权限执行的命令
|
||||
+ `/fp spawn [世界] [位置]` - 创建假人
|
||||
+ `/fp kill [假人]` - 移除假人
|
||||
+ `/fp list [页码] [数量]` - 查看所有假人
|
||||
+ `/fp distance` - 查看与假人的距离
|
||||
+ `/fp tp [假人]` - 传送到假人身边
|
||||
+ `/fp tphere [假人]` - 将假人传送到身边
|
||||
+ `/fp tps [假人]` - 与假人交换位置
|
||||
+ `/fp config get <配置项>` - 查看配置项
|
||||
+ `/fp config set <配置项> <配置值>` - 设置配置项
|
||||
+ `/fp health [假人]` - 查看生命值
|
||||
+ `/fp exp [假人]` - 查看经验值
|
||||
+ `/fp expme [假人]` - 转移经验值
|
||||
+ `/fp attack (once | continuous | interval | stop) [假人]` - 攻击/破坏
|
||||
+ `/fp use (once | continuous | interval | stop) [假人]` - 使用/交互/放置
|
||||
+ `/fp jump (once | continuous | interval | stop) [假人]` - 跳跃
|
||||
+ `/fp drop [假人] [-a|--all]` - 丢弃手上物品
|
||||
+ `/fp dropinv [假人]` - 丢弃背包物品
|
||||
+ `/fp look (north | south | east| west | up | down | at) [假人]` - 看向指定位置
|
||||
+ `/fp turn (left | right | back | to) [假人]` - 转身到指定位置
|
||||
+ `/fp move (forward | backward | left | right) [假人]` - 移动假人
|
||||
+ `/fp cmd <假人>` - 执行命令
|
||||
+ `/fp reload` - 重载配置文件
|
||||
|
||||
此外,假人是一个模拟玩家,因此可以被任何指令所识别比如 `kick`, `tp`, `ban` 等等
|
||||
|
||||
|
@ -42,7 +42,12 @@ public class ActionCommand extends AbstractCommand {
|
||||
return (sender, args) -> action(sender, args, action, setting.clone());
|
||||
}
|
||||
|
||||
public void action(@NotNull CommandSender sender, @NotNull CommandArguments args, @NotNull Action action, @NotNull ActionSetting setting) throws WrapperCommandSyntaxException {
|
||||
public void action(
|
||||
@NotNull CommandSender sender,
|
||||
@NotNull CommandArguments args,
|
||||
@NotNull Action action,
|
||||
@NotNull ActionSetting setting
|
||||
) throws WrapperCommandSyntaxException {
|
||||
var target = getTarget(sender, args);
|
||||
actionManager.setAction(target, action, setting);
|
||||
|
||||
|
@ -55,7 +55,7 @@ public class Commands {
|
||||
"§6/fp look (north|south|east|west|up|down|at) [假人] §7- §f看向指定位置",
|
||||
"§6/fp turn (left|right|back|to) [假人] §7- §f转身到指定位置",
|
||||
"§6/fp move (forward|backward|left|right) [假人] §7- §f移动假人",
|
||||
"§6/fp cmd §7- §f执行命令",
|
||||
"§6/fp cmd <假人> <命令> §7- §f执行命令",
|
||||
"§6/fp reload §7- §f重载配置文件"
|
||||
)
|
||||
.withSubcommands(
|
||||
|
@ -24,7 +24,7 @@ public class ConfigCommand extends AbstractCommand {
|
||||
|
||||
private final UserConfigRepository repository = UserConfigRepository.instance;
|
||||
|
||||
public static Argument<Config<Object>> config(String nodeName) {
|
||||
public static Argument<Config<Object>> config(@NotNull String nodeName) {
|
||||
return new CustomArgument<>(new StringArgument(nodeName), info -> {
|
||||
var arg = info.currentInput();
|
||||
try {
|
||||
@ -35,7 +35,7 @@ public class ConfigCommand extends AbstractCommand {
|
||||
}).replaceSuggestions(ArgumentSuggestions.strings(Arrays.stream(Configs.values()).map(Config::name).toList()));
|
||||
}
|
||||
|
||||
public static Argument<Object> configValue(String configNodeName, String nodeName) {
|
||||
public static Argument<Object> configValue(@NotNull String configNodeName, @NotNull String nodeName) {
|
||||
return new CustomArgument<>(new StringArgument(nodeName), info -> {
|
||||
@SuppressWarnings("unchecked")
|
||||
var config = Objects.requireNonNull((Config<Object>) info.previousArgs().get(configNodeName));
|
||||
|
@ -34,7 +34,7 @@ public class SpawnCommand extends AbstractCommand {
|
||||
MathUtils.round(location.getZ(), 0.5));
|
||||
}
|
||||
|
||||
public void spawn(@NotNull CommandSender sender, CommandArguments args) {
|
||||
public void spawn(@NotNull CommandSender sender, @NotNull CommandArguments args) {
|
||||
var world = (World) args.get("world");
|
||||
var location = (Location) args.get("location");
|
||||
if (world == null || location == null) {
|
||||
@ -48,7 +48,7 @@ public class SpawnCommand extends AbstractCommand {
|
||||
location.setWorld(world);
|
||||
}
|
||||
|
||||
var fakePlayer = fakeplayerManager.spawn(sender, location.clone());
|
||||
var fakePlayer = fakeplayerManager.spawn(sender, location);
|
||||
if (fakePlayer != null) {
|
||||
sender.sendMessage(textOfChildren(
|
||||
text("你创建了假人 ", GRAY),
|
||||
@ -59,7 +59,7 @@ public class SpawnCommand extends AbstractCommand {
|
||||
}
|
||||
}
|
||||
|
||||
public void kill(@NotNull CommandSender sender, CommandArguments args) {
|
||||
public void kill(@NotNull CommandSender sender, @NotNull CommandArguments args) {
|
||||
@SuppressWarnings("unchecked")
|
||||
var targets = (List<Player>) args.get("targets");
|
||||
if (targets == null) {
|
||||
|
@ -2,14 +2,10 @@ package io.github.hello09x.fakeplayer.command;
|
||||
|
||||
import dev.jorel.commandapi.exceptions.WrapperCommandSyntaxException;
|
||||
import dev.jorel.commandapi.executors.CommandArguments;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.SoundCategory;
|
||||
import io.github.hello09x.fakeplayer.util.Teleportor;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.player.PlayerTeleportEvent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import static org.bukkit.Sound.ENTITY_ENDERMAN_TELEPORT;
|
||||
|
||||
public class TpCommand extends AbstractCommand {
|
||||
|
||||
public final static TpCommand instance = new TpCommand();
|
||||
@ -27,19 +23,15 @@ public class TpCommand extends AbstractCommand {
|
||||
public void tps(@NotNull Player sender, @NotNull CommandArguments args) throws WrapperCommandSyntaxException {
|
||||
var target = getTarget(sender, args);
|
||||
|
||||
var l1 = sender.getLocation();
|
||||
var l2 = target.getLocation();
|
||||
var l1 = sender.getLocation().clone();
|
||||
var l2 = target.getLocation().clone();
|
||||
|
||||
target.teleport(l1, PlayerTeleportEvent.TeleportCause.PLUGIN);
|
||||
l1.getWorld().playSound(l1, Sound.ENTITY_ENDERMAN_TELEPORT, SoundCategory.PLAYERS, 1.0F, 1.0F);
|
||||
|
||||
sender.teleport(l2, PlayerTeleportEvent.TeleportCause.PLUGIN);
|
||||
l2.getWorld().playSound(l2, Sound.ENTITY_ENDERMAN_TELEPORT, SoundCategory.PLAYERS, 1.0F, 1.0F);
|
||||
Teleportor.teleportAndSound(target, l1);
|
||||
Teleportor.teleportAndSound(sender, l2);
|
||||
}
|
||||
|
||||
private void teleport(@NotNull Player from, @NotNull Player to) {
|
||||
from.teleport(to.getLocation(), PlayerTeleportEvent.TeleportCause.PLUGIN);
|
||||
to.getLocation().getWorld().playSound(to.getLocation(), ENTITY_ENDERMAN_TELEPORT, 1.0F, 1.0F);
|
||||
Teleportor.teleportAndSound(from, to.getLocation());
|
||||
}
|
||||
|
||||
|
||||
|
@ -9,11 +9,11 @@ import io.github.hello09x.fakeplayer.repository.UsedIdRepository;
|
||||
import io.github.hello09x.fakeplayer.repository.UserConfigRepository;
|
||||
import io.github.hello09x.fakeplayer.repository.model.Configs;
|
||||
import io.github.hello09x.fakeplayer.util.AddressUtils;
|
||||
import io.github.hello09x.fakeplayer.util.Teleportor;
|
||||
import io.github.hello09x.fakeplayer.util.Unwrapper;
|
||||
import net.kyori.adventure.text.format.Style;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.craftbukkit.v1_20_R1.CraftServer;
|
||||
import org.bukkit.entity.Player;
|
||||
@ -94,7 +94,7 @@ public class FakeplayerManager {
|
||||
return null;
|
||||
}
|
||||
|
||||
var seqname = nameManager.take(creator);
|
||||
var sn = nameManager.take(creator);
|
||||
boolean invulnerable = true, lookAtEntity = true, collidable = true, pickupItems = true;
|
||||
if (creator instanceof Player p) {
|
||||
var creatorId = p.getUniqueId();
|
||||
@ -107,16 +107,16 @@ public class FakeplayerManager {
|
||||
var player = new FakePlayer(
|
||||
creator.getName(),
|
||||
((CraftServer) Bukkit.getServer()).getServer(),
|
||||
generateId(seqname.name()),
|
||||
seqname.name()
|
||||
generateId(sn.name()),
|
||||
sn.name()
|
||||
);
|
||||
|
||||
var bukkitPlayer = player.getBukkitPlayer();
|
||||
Metadatas.CREATOR.set(bukkitPlayer, creator.getName());
|
||||
Metadatas.CREATOR_IP.set(bukkitPlayer, AddressUtils.getAddress(creator));
|
||||
Metadatas.NAME_SOURCE.set(bukkitPlayer, seqname.source());
|
||||
Metadatas.NAME_SEQUENCE.set(bukkitPlayer, seqname.sequence());
|
||||
bukkitPlayer.playerListName(text(creator.getName() + "的假人").style(Style.style(GRAY, ITALIC)));
|
||||
Metadatas.NAME_SOURCE.set(bukkitPlayer, sn.source());
|
||||
Metadatas.NAME_SEQUENCE.set(bukkitPlayer, sn.sequence());
|
||||
bukkitPlayer.playerListName(text(bukkitPlayer.getName() + " (假人)").style(Style.style(GRAY, ITALIC)));
|
||||
|
||||
player.spawn(invulnerable, collidable, lookAtEntity, pickupItems);
|
||||
|
||||
@ -124,29 +124,30 @@ public class FakeplayerManager {
|
||||
dispatchCommands(bukkitPlayer, properties.getPreparingCommands());
|
||||
performCommands(bukkitPlayer, properties.getSelfCommands());
|
||||
|
||||
bukkitPlayer.teleport(spawnAt); // 当前 tick 必须传到出生点否则无法触发区块刷新
|
||||
spawnAt.getWorld().playSound(spawnAt, Sound.ENTITY_ENDERMAN_TELEPORT, 1.0F, 1.0F);
|
||||
spawnAt = spawnAt.clone();
|
||||
Teleportor.teleportAndSound(bukkitPlayer, spawnAt); // 当前 tick 必须传到出生点否则无法触发区块刷新
|
||||
ensureSpawnpoint(bukkitPlayer, spawnAt); // 防止别的插件比如 `multicore` 把他带离出生点
|
||||
|
||||
// 可能被别的插件干预
|
||||
// 在下一 tick 里探测
|
||||
return bukkitPlayer;
|
||||
}
|
||||
|
||||
private void ensureSpawnpoint(@NotNull Player player, @NotNull Location spawnpoint) {
|
||||
new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (spawnAt.distance(bukkitPlayer.getLocation()) < 16) {
|
||||
if (spawnpoint.getWorld().equals(spawnpoint.getWorld()) && spawnpoint.distance(player.getLocation()) < 16) {
|
||||
return;
|
||||
}
|
||||
|
||||
bukkitPlayer.teleport(spawnAt.getWorld().getSpawnLocation());
|
||||
player.teleport(spawnpoint.getWorld().getSpawnLocation());
|
||||
new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
bukkitPlayer.teleport(spawnAt);
|
||||
player.teleport(spawnpoint);
|
||||
}
|
||||
}.runTaskLater(Main.getInstance(), 1);
|
||||
}
|
||||
}.runTaskLater(Main.getInstance(), 1);
|
||||
|
||||
return bukkitPlayer;
|
||||
}
|
||||
|
||||
public @Nullable Player get(@NotNull CommandSender creator, @NotNull String name) {
|
||||
|
@ -14,14 +14,12 @@ import java.util.logging.Logger;
|
||||
public class NameManager {
|
||||
|
||||
public final static NameManager instance = new NameManager();
|
||||
|
||||
private final static Logger log = Main.getInstance().getLogger();
|
||||
private final static int MAX_LENGTH = 16; // mojang required
|
||||
private final FakeplayerProperties properties = FakeplayerProperties.instance;
|
||||
|
||||
private final ConcurrentHashMap<String, NameSource> nameSources = new ConcurrentHashMap<>();
|
||||
|
||||
private final static Logger log = Main.getInstance().getLogger();
|
||||
|
||||
public SequenceName take(CommandSender creator) {
|
||||
public @NotNull SequenceName take(CommandSender creator) {
|
||||
var source = properties.getNameTemplate();
|
||||
if (source.isBlank()) {
|
||||
source = creator.getName();
|
||||
@ -33,8 +31,8 @@ public class NameManager {
|
||||
var suffix = "_" + (seq + 1);
|
||||
|
||||
String name;
|
||||
if (source.length() + suffix.length() > 16) {
|
||||
name = source.substring(0, (16 - suffix.length()));
|
||||
if (source.length() + suffix.length() > MAX_LENGTH) {
|
||||
name = source.substring(0, (MAX_LENGTH - suffix.length()));
|
||||
} else {
|
||||
name = source;
|
||||
}
|
||||
@ -52,7 +50,8 @@ public class NameManager {
|
||||
);
|
||||
}
|
||||
|
||||
var name = "FAKE_" + RandomStringUtils.random(11, true, true);
|
||||
var name = "_fp_";
|
||||
name = name + RandomStringUtils.random(MAX_LENGTH - name.length(), true, true);
|
||||
log.warning("Could not generate a name which is never used at this server after 10 tries, using random player name as fallback: " + name);
|
||||
return new SequenceName("random", 0, name);
|
||||
}
|
||||
|
@ -20,8 +20,7 @@ public class NameSource {
|
||||
this(0);
|
||||
}
|
||||
|
||||
public
|
||||
synchronized int pop() {
|
||||
public synchronized int pop() {
|
||||
if (names.isEmpty()) {
|
||||
var newCapacity = capacity * 2;
|
||||
for (int i = capacity; i < newCapacity; i++) {
|
||||
|
@ -0,0 +1,16 @@
|
||||
package io.github.hello09x.fakeplayer.util;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class Teleportor {
|
||||
|
||||
public static void teleportAndSound(@NotNull Entity entity, @NotNull Location location) {
|
||||
entity.teleport(location);
|
||||
location.getWorld().playSound(location, Sound.ENTITY_ENDERMAN_TELEPORT, 1.0F, 1.0F);;
|
||||
}
|
||||
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user