使用 Guice 组织类

This commit is contained in:
tanyaofei 2024-07-06 20:04:28 +08:00
parent 3f6e85aa48
commit 0a9446c252
52 changed files with 439 additions and 285 deletions

View File

@ -12,16 +12,6 @@ import java.util.ServiceLoader;
public interface NMSBridge { public interface NMSBridge {
static @Nullable NMSBridge getInstance() {
return ServiceLoader
.load(NMSBridge.class, NMSBridge.class.getClassLoader())
.stream()
.map(ServiceLoader.Provider::get)
.filter(NMSBridge::isSupported)
.findAny()
.orElse(null);
}
@NotNull NMSEntity fromEntity(@NotNull Entity entity); @NotNull NMSEntity fromEntity(@NotNull Entity entity);
@NotNull NMSServer fromServer(@NotNull Server server); @NotNull NMSServer fromServer(@NotNull Server server);

View File

@ -57,6 +57,11 @@
<groupId>com.github.jikoo.OpenInv</groupId> <groupId>com.github.jikoo.OpenInv</groupId>
<artifactId>openinvapi</artifactId> <artifactId>openinvapi</artifactId>
</dependency> </dependency>
<dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
</dependency>
</dependencies> </dependencies>
<build> <build>

View File

@ -0,0 +1,57 @@
package io.github.hello09x.fakeplayer.core;
import com.google.common.base.Throwables;
import com.google.inject.AbstractModule;
import io.github.hello09x.fakeplayer.api.spi.NMSBridge;
import io.github.hello09x.fakeplayer.core.config.FakeplayerConfig;
import io.github.hello09x.fakeplayer.core.manager.invsee.DefaultInvseeImpl;
import io.github.hello09x.fakeplayer.core.manager.invsee.Invsee;
import io.github.hello09x.fakeplayer.core.manager.invsee.OpenInvInvseeImpl;
import org.bukkit.Bukkit;
import java.util.ServiceLoader;
import java.util.logging.Logger;
public class FakeplayerGuiceModule extends AbstractModule {
private final Logger log = Main.getInstance().getLogger();
@Override
protected void configure() {
super.bind(FakeplayerConfig.class).toProvider(this::fakeplayerConfig);
super.bind(Invsee.class).toProvider(this::invsee);
super.bind(NMSBridge.class).toInstance(nmsBridge());
}
private FakeplayerConfig fakeplayerConfig() {
return new FakeplayerConfig(Main.getInstance(), "13");
}
private Invsee invsee() {
if (Bukkit.getPluginManager().getPlugin("OpenInv") != null) {
try {
return new OpenInvInvseeImpl();
} catch(Throwable e) {
log.warning(Throwables.getStackTraceAsString(e));
}
}
return new DefaultInvseeImpl();
}
private NMSBridge nmsBridge() {
var bridge = ServiceLoader
.load(NMSBridge.class, NMSBridge.class.getClassLoader())
.stream()
.map(ServiceLoader.Provider::get)
.filter(NMSBridge::isSupported)
.findAny()
.orElse(null);
if (bridge == null) {
throw new ExceptionInInitializerError("Unsupported Minecraft version: " + Bukkit.getMinecraftVersion());
}
return bridge;
}
}

View File

@ -1,5 +1,8 @@
package io.github.hello09x.fakeplayer.core; package io.github.hello09x.fakeplayer.core;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import io.github.hello09x.bedrock.i18n.I18n; import io.github.hello09x.bedrock.i18n.I18n;
import io.github.hello09x.bedrock.i18n.I18nSupported; import io.github.hello09x.bedrock.i18n.I18nSupported;
import io.github.hello09x.bedrock.util.RegistrablePlugin; import io.github.hello09x.bedrock.util.RegistrablePlugin;
@ -22,40 +25,50 @@ public final class Main extends RegistrablePlugin implements I18nSupported {
@Getter @Getter
private static Main instance; private static Main instance;
@Getter
private static NMSBridge bridge;
private I18n i18n; private I18n i18n;
private Injector injector;
@Inject
FakeplayerConfig config;
@Inject
WildFakeplayerManager wildFakeplayerManager;
@Inject
PlayerListeners playerListeners;
@Inject
FakeplayerListener fakeplayerListener;
@Inject
ReplenishListener replenishListener;
@Override @Override
public void onLoad() { public void onLoad() {
bridge = NMSBridge.getInstance(); instance = this;
if (bridge == null) { injector = Guice.createInjector(new FakeplayerGuiceModule());
throw new ExceptionInInitializerError("Unsupported Minecraft version: " + Bukkit.getMinecraftVersion());
}
this.i18n = new I18n(this, "message/message"); this.i18n = new I18n(this, "message/message");
} }
@Override @Override
public void onEnable() { public void onEnable() {
// Plugin startup logic injector.injectMembers(this);
instance = this; injector.getInstance(CommandRegistry.class).register();
CommandRegistry.register();
{ {
var messenger = getServer().getMessenger(); var messenger = getServer().getMessenger();
messenger.registerIncomingPluginChannel(this, "BungeeCord", WildFakeplayerManager.instance); messenger.registerIncomingPluginChannel(this, "BungeeCord", wildFakeplayerManager);
messenger.registerOutgoingPluginChannel(this, "BungeeCord"); messenger.registerOutgoingPluginChannel(this, "BungeeCord");
} }
{ {
var manager = getServer().getPluginManager(); var manager = getServer().getPluginManager();
manager.registerEvents(PlayerListeners.instance, this); manager.registerEvents(playerListeners, this);
manager.registerEvents(FakeplayerListener.instance, this); manager.registerEvents(fakeplayerListener, this);
manager.registerEvents(ReplenishListener.instance, this); manager.registerEvents(replenishListener, this);
} }
if (FakeplayerConfig.instance.isCheckForUpdates()) { if (config.isCheckForUpdates()) {
checkForUpdatesAsync(); checkForUpdatesAsync();
} }
} }
@ -108,4 +121,8 @@ public final class Main extends RegistrablePlugin implements I18nSupported {
return instance.i18n; return instance.i18n;
} }
public static @NotNull Injector getInjector() {
return instance.injector;
}
} }

View File

@ -1,5 +1,7 @@
package io.github.hello09x.fakeplayer.core.command; package io.github.hello09x.fakeplayer.core.command;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import dev.jorel.commandapi.CommandPermission; import dev.jorel.commandapi.CommandPermission;
import io.github.hello09x.bedrock.command.Usage; import io.github.hello09x.bedrock.command.Usage;
import io.github.hello09x.bedrock.i18n.I18n; import io.github.hello09x.bedrock.i18n.I18n;
@ -7,6 +9,7 @@ import io.github.hello09x.fakeplayer.api.spi.Action;
import io.github.hello09x.fakeplayer.core.Main; import io.github.hello09x.fakeplayer.core.Main;
import io.github.hello09x.fakeplayer.core.command.impl.*; import io.github.hello09x.fakeplayer.core.command.impl.*;
import io.github.hello09x.fakeplayer.core.constant.Direction; import io.github.hello09x.fakeplayer.core.constant.Direction;
import io.github.hello09x.fakeplayer.core.manager.invsee.Invsee;
import io.github.hello09x.fakeplayer.core.repository.model.Config; import io.github.hello09x.fakeplayer.core.repository.model.Config;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity; import org.bukkit.entity.LivingEntity;
@ -17,13 +20,63 @@ import static io.github.hello09x.bedrock.command.Commands.*;
import static io.github.hello09x.fakeplayer.core.command.CommandSupports.*; import static io.github.hello09x.fakeplayer.core.command.CommandSupports.*;
@Singleton
@SuppressWarnings("SameParameterValue") @SuppressWarnings("SameParameterValue")
public class CommandRegistry { public class CommandRegistry {
private final static I18n i18n = Main.getI18n(); private final static I18n i18n = Main.getI18n();
@Inject
private ActionCommand actionCommand;
@Inject
private CmdCommand cmdCommand;
@Inject
private ConfigCommand configCommand;
@Inject
private DistanceCommand distanceCommand;
@Inject
private ExpmeCommand expmeCommand;
@Inject
private HoldCommand holdCommand;
@Inject
private InvseeCommand invseeCommand;
@Inject
private KillCommand killCommand;
@Inject
private KillallCommand killallCommand;
@Inject
private ListCommand listCommand;
@Inject
private MoveCommand moveCommand;
@Inject
private ReloadCommand reloadCommand;
@Inject
private RespawnCommand respawnCommand;
@Inject
private RideCommand rideCommand;
@Inject
private RotationCommand rotationCommand;
@Inject
private SelectCommand selectCommand;
@Inject
private SetCommand setCommand;
@Inject
private SkinCommand skinCommand;
@Inject
private SleepCommand sleepCommand;
@Inject
private SneakCommand sneakCommand;
@Inject
private SpawnCommand spawnCommand;
@Inject
private StatusCommand statusCommand;
@Inject
private SwapCommand swapCommand;
@Inject
private TeleportCommand teleportCommand;
public static void register() { public void register() {
command("fakeplayer") command("fakeplayer")
.withAliases("fp") .withAliases("fp")
.withHelp( .withHelp(
@ -78,11 +131,11 @@ public class CommandRegistry {
.withPermission(Permission.select) .withPermission(Permission.select)
.withRequirement(CommandSupports::needSelect) .withRequirement(CommandSupports::needSelect)
.withOptionalArguments(target("name")) .withOptionalArguments(target("name"))
.executesPlayer(SelectCommand.instance::select), .executesPlayer(selectCommand::select),
command("selection") command("selection")
.withPermission(Permission.select) .withPermission(Permission.select)
.withRequirement(CommandSupports::needSelect) .withRequirement(CommandSupports::needSelect)
.executesPlayer(SelectCommand.instance::selection), .executesPlayer(selectCommand::selection),
command("spawn") command("spawn")
.withPermission(Permission.spawn) .withPermission(Permission.spawn)
@ -90,51 +143,51 @@ public class CommandRegistry {
text("name").withPermission(Permission.spawnName), text("name").withPermission(Permission.spawnName),
world("world").withPermission(Permission.spawnLocation), world("world").withPermission(Permission.spawnLocation),
location("location").withPermission(Permission.spawnLocation)) location("location").withPermission(Permission.spawnLocation))
.executes(SpawnCommand.instance::spawn), .executes(spawnCommand::spawn),
command("kill") command("kill")
.withPermission(Permission.kill) .withPermission(Permission.kill)
.withRequirement(CommandSupports::hasTarget) .withRequirement(CommandSupports::hasTarget)
.withOptionalArguments(targets("names")) .withOptionalArguments(targets("names"))
.executes(KillCommand.instance::kill), .executes(killCommand::kill),
command("list") command("list")
.withPermission(Permission.list) .withPermission(Permission.list)
.withRequirement(CommandSupports::hasTarget) .withRequirement(CommandSupports::hasTarget)
.withOptionalArguments( .withOptionalArguments(
int32("page", 1), int32("page", 1),
int32("size", 1)) int32("size", 1))
.executes(ListCommand.instance::list), .executes(listCommand::list),
command("distance") command("distance")
.withPermission(Permission.distance) .withPermission(Permission.distance)
.withRequirement(CommandSupports::hasTarget) .withRequirement(CommandSupports::hasTarget)
.withOptionalArguments(target("name")) .withOptionalArguments(target("name"))
.executesPlayer(DistanceCommand.instance::distance), .executesPlayer(distanceCommand::distance),
command("skin") command("skin")
.withPermission(Permission.skin) .withPermission(Permission.skin)
.withRequirement(CommandSupports::hasTarget) .withRequirement(CommandSupports::hasTarget)
.withArguments(offlinePlayer("player")) .withArguments(offlinePlayer("player"))
.withOptionalArguments(target("name")) .withOptionalArguments(target("name"))
.executes(SkinCommand.instance::skin), .executes(skinCommand::skin),
command("invsee") command("invsee")
.withPermission(Permission.invsee) .withPermission(Permission.invsee)
.withRequirement(CommandSupports::hasTarget) .withRequirement(CommandSupports::hasTarget)
.withOptionalArguments(target("name")) .withOptionalArguments(target("name"))
.executesPlayer(InvseeCommand.instance::invsee), .executesPlayer(invseeCommand::invsee),
command("hold") command("hold")
.withPermission(Permission.hold) .withPermission(Permission.hold)
.withRequirement(CommandSupports::hasTarget) .withRequirement(CommandSupports::hasTarget)
.withArguments(int32("slot", 1, 9)) .withArguments(int32("slot", 1, 9))
.withOptionalArguments(target("name")) .withOptionalArguments(target("name"))
.executes(HoldCommand.instance::hold), .executes(holdCommand::hold),
command("status") command("status")
.withPermission(Permission.status) .withPermission(Permission.status)
.withRequirement(CommandSupports::hasTarget) .withRequirement(CommandSupports::hasTarget)
.withOptionalArguments(target("name")) .withOptionalArguments(target("name"))
.executes(StatusCommand.instance::status), .executes(statusCommand::status),
command("respawn") command("respawn")
.withRequirement(CommandSupports::hasDeadTarget) .withRequirement(CommandSupports::hasDeadTarget)
.withPermission(Permission.respawn) .withPermission(Permission.respawn)
.withOptionalArguments(target("name", Entity::isDead)) .withOptionalArguments(target("name", Entity::isDead))
.executes(RespawnCommand.instance::respawn), .executes(respawnCommand::respawn),
command("set") command("set")
.withRequirement(CommandSupports::hasTarget) .withRequirement(CommandSupports::hasTarget)
.withPermission(Permission.set) .withPermission(Permission.set)
@ -143,7 +196,7 @@ public class CommandRegistry {
configValue("config", "value") configValue("config", "value")
) )
.withOptionalArguments(target("name")) .withOptionalArguments(target("name"))
.executes(SetCommand.instance::set), .executes(setCommand::set),
command("config") command("config")
.withPermission(Permission.config) .withPermission(Permission.config)
.withSubcommands( .withSubcommands(
@ -151,102 +204,102 @@ public class CommandRegistry {
.withArguments( .withArguments(
config("config"), config("config"),
configValue("config", "value")) configValue("config", "value"))
.executesPlayer(ConfigCommand.instance::setConfig), .executesPlayer(configCommand::setConfig),
command("list") command("list")
.executes(ConfigCommand.instance::listConfig) .executes(configCommand::listConfig)
) )
.executes(ConfigCommand.instance::listConfig), .executes(configCommand::listConfig),
command("expme") command("expme")
.withPermission(Permission.expme) .withPermission(Permission.expme)
.withRequirement(CommandSupports::hasTarget) .withRequirement(CommandSupports::hasTarget)
.withOptionalArguments(target("name")) .withOptionalArguments(target("name"))
.executesPlayer(ExpmeCommand.instance::expme), .executesPlayer(expmeCommand::expme),
command("tp") command("tp")
.withPermission(Permission.tp) .withPermission(Permission.tp)
.withRequirement(CommandSupports::hasTarget) .withRequirement(CommandSupports::hasTarget)
.withOptionalArguments(target("name")) .withOptionalArguments(target("name"))
.executesPlayer(TeleportCommand.instance::tp), .executesPlayer(teleportCommand::tp),
command("tphere") command("tphere")
.withPermission(Permission.tphere) .withPermission(Permission.tphere)
.withRequirement(CommandSupports::hasTarget) .withRequirement(CommandSupports::hasTarget)
.withOptionalArguments(target("name")) .withOptionalArguments(target("name"))
.executesPlayer(TeleportCommand.instance::tphere), .executesPlayer(teleportCommand::tphere),
command("tps") command("tps")
.withPermission(Permission.tps) .withPermission(Permission.tps)
.withRequirement(CommandSupports::hasTarget) .withRequirement(CommandSupports::hasTarget)
.withOptionalArguments(target("name")) .withOptionalArguments(target("name"))
.executesPlayer(TeleportCommand.instance::tps), .executesPlayer(teleportCommand::tps),
command("attack") command("attack")
.withPermission(Permission.attack) .withPermission(Permission.attack)
.withRequirement(CommandSupports::hasTarget) .withRequirement(CommandSupports::hasTarget)
.withSubcommands(newActionCommands(Action.ActionType.ATTACK)) .withSubcommands(newActionCommands(Action.ActionType.ATTACK))
.executes(ActionCommand.instance.action(Action.ActionType.ATTACK, Action.ActionSetting.once())), .executes(actionCommand.action(Action.ActionType.ATTACK, Action.ActionSetting.once())),
command("mine") command("mine")
.withPermission(Permission.mine) .withPermission(Permission.mine)
.withRequirement(CommandSupports::hasTarget) .withRequirement(CommandSupports::hasTarget)
.withSubcommands(newActionCommands(Action.ActionType.MINE)) .withSubcommands(newActionCommands(Action.ActionType.MINE))
.executes(ActionCommand.instance.action(Action.ActionType.MINE, Action.ActionSetting.once())), .executes(actionCommand.action(Action.ActionType.MINE, Action.ActionSetting.once())),
command("use") command("use")
.withPermission(Permission.use) .withPermission(Permission.use)
.withRequirement(CommandSupports::hasTarget) .withRequirement(CommandSupports::hasTarget)
.withSubcommands(newActionCommands(Action.ActionType.USE)) .withSubcommands(newActionCommands(Action.ActionType.USE))
.executes(ActionCommand.instance.action(Action.ActionType.USE, Action.ActionSetting.once())), .executes(actionCommand.action(Action.ActionType.USE, Action.ActionSetting.once())),
command("jump") command("jump")
.withPermission(Permission.jump) .withPermission(Permission.jump)
.withRequirement(CommandSupports::hasTarget) .withRequirement(CommandSupports::hasTarget)
.withSubcommands(newActionCommands(Action.ActionType.JUMP)) .withSubcommands(newActionCommands(Action.ActionType.JUMP))
.executes(ActionCommand.instance.action(Action.ActionType.JUMP, Action.ActionSetting.once())), .executes(actionCommand.action(Action.ActionType.JUMP, Action.ActionSetting.once())),
command("drop") command("drop")
.withPermission(Permission.drop) .withPermission(Permission.drop)
.withRequirement(CommandSupports::hasTarget) .withRequirement(CommandSupports::hasTarget)
.withSubcommands(newActionCommands(Action.ActionType.DROP_ITEM)) .withSubcommands(newActionCommands(Action.ActionType.DROP_ITEM))
.executes(ActionCommand.instance.action(Action.ActionType.DROP_ITEM, Action.ActionSetting.once())), .executes(actionCommand.action(Action.ActionType.DROP_ITEM, Action.ActionSetting.once())),
command("dropstack") command("dropstack")
.withPermission(Permission.dropstack) .withPermission(Permission.dropstack)
.withRequirement(CommandSupports::hasTarget) .withRequirement(CommandSupports::hasTarget)
.withSubcommands(newActionCommands(Action.ActionType.DROP_STACK)) .withSubcommands(newActionCommands(Action.ActionType.DROP_STACK))
.executes(ActionCommand.instance.action(Action.ActionType.DROP_STACK, Action.ActionSetting.once())), .executes(actionCommand.action(Action.ActionType.DROP_STACK, Action.ActionSetting.once())),
command("dropinv") command("dropinv")
.withPermission(Permission.dropinv) .withPermission(Permission.dropinv)
.withRequirement(CommandSupports::hasTarget) .withRequirement(CommandSupports::hasTarget)
.withSubcommands(newActionCommands(Action.ActionType.DROP_INVENTORY)) .withSubcommands(newActionCommands(Action.ActionType.DROP_INVENTORY))
.executes(ActionCommand.instance.action(Action.ActionType.DROP_INVENTORY, Action.ActionSetting.once())), .executes(actionCommand.action(Action.ActionType.DROP_INVENTORY, Action.ActionSetting.once())),
command("sneak") command("sneak")
.withPermission(Permission.sneak) .withPermission(Permission.sneak)
.withRequirement(CommandSupports::hasTarget) .withRequirement(CommandSupports::hasTarget)
.withOptionalArguments( .withOptionalArguments(
target("name"), target("name"),
literals("sneaking", List.of("true", "false"))) literals("sneaking", List.of("true", "false")))
.executes(SneakCommand.instance::sneak), .executes(sneakCommand::sneak),
command("look") command("look")
.withPermission(Permission.look) .withPermission(Permission.look)
.withRequirement(CommandSupports::hasTarget) .withRequirement(CommandSupports::hasTarget)
.withSubcommands( .withSubcommands(
command("north") command("north")
.withOptionalArguments(target("name")) .withOptionalArguments(target("name"))
.executes(RotationCommand.instance.look(Direction.NORTH)), .executes(rotationCommand.look(Direction.NORTH)),
command("south") command("south")
.withOptionalArguments(target("name")) .withOptionalArguments(target("name"))
.executes(RotationCommand.instance.look(Direction.SOUTH)), .executes(rotationCommand.look(Direction.SOUTH)),
command("west") command("west")
.withOptionalArguments(target("name")) .withOptionalArguments(target("name"))
.executes(RotationCommand.instance.look(Direction.WEST)), .executes(rotationCommand.look(Direction.WEST)),
command("east") command("east")
.withOptionalArguments(target("name")) .withOptionalArguments(target("name"))
.executes(RotationCommand.instance.look(Direction.EAST)), .executes(rotationCommand.look(Direction.EAST)),
command("up") command("up")
.withOptionalArguments(target("name")) .withOptionalArguments(target("name"))
.executes(RotationCommand.instance.look(Direction.UP)), .executes(rotationCommand.look(Direction.UP)),
command("down") command("down")
.withOptionalArguments(target("name")) .withOptionalArguments(target("name"))
.executes(RotationCommand.instance.look(Direction.DOWN)), .executes(rotationCommand.look(Direction.DOWN)),
command("at") command("at")
.withArguments(location("location")) .withArguments(location("location"))
.withOptionalArguments(target("name")) .withOptionalArguments(target("name"))
.executes(RotationCommand.instance::lookAt), .executes(rotationCommand::lookAt),
command("entity") command("entity")
.withOptionalArguments(target("name")) .withOptionalArguments(target("name"))
.withSubcommands(newActionCommands(Action.ActionType.LOOK_AT_NEAREST_ENTITY)), .withSubcommands(newActionCommands(Action.ActionType.LOOK_AT_NEAREST_ENTITY)),
@ -268,17 +321,17 @@ public class CommandRegistry {
.withSubcommands( .withSubcommands(
command("left") command("left")
.withOptionalArguments(target("name")) .withOptionalArguments(target("name"))
.executes(RotationCommand.instance.turn(-90, 0)), .executes(rotationCommand.turn(-90, 0)),
command("right") command("right")
.withOptionalArguments(target("name")) .withOptionalArguments(target("name"))
.executes(RotationCommand.instance.turn(90, 0)), .executes(rotationCommand.turn(90, 0)),
command("back") command("back")
.withOptionalArguments(target("name")) .withOptionalArguments(target("name"))
.executes(RotationCommand.instance.turn(180, 0)), .executes(rotationCommand.turn(180, 0)),
command("to") command("to")
.withArguments(rotation("rotation")) .withArguments(rotation("rotation"))
.withOptionalArguments(target("name")) .withOptionalArguments(target("name"))
.executes(RotationCommand.instance::turnTo), .executes(rotationCommand::turnTo),
helpCommand( helpCommand(
"/fp turn", "/fp turn",
Usage.of("left", i18n.asString("fakeplayer.command.turn.left.description")), Usage.of("left", i18n.asString("fakeplayer.command.turn.left.description")),
@ -293,16 +346,16 @@ public class CommandRegistry {
.withSubcommands( .withSubcommands(
command("forward") command("forward")
.withOptionalArguments(target("name")) .withOptionalArguments(target("name"))
.executes(MoveCommand.instance.move(1, 0)), .executes(moveCommand.move(1, 0)),
command("backward") command("backward")
.withOptionalArguments(target("name")) .withOptionalArguments(target("name"))
.executes(MoveCommand.instance.move(-1, 0)), .executes(moveCommand.move(-1, 0)),
command("left") command("left")
.withOptionalArguments(target("name")) .withOptionalArguments(target("name"))
.executes(MoveCommand.instance.move(0, 1)), .executes(moveCommand.move(0, 1)),
command("right") command("right")
.withOptionalArguments(target("name")) .withOptionalArguments(target("name"))
.executes(MoveCommand.instance.move(0, -1)), .executes(moveCommand.move(0, -1)),
helpCommand( helpCommand(
"/fp move", "/fp move",
Usage.of("forward", i18n.asString("fakeplayer.command.move.forward.description")), Usage.of("forward", i18n.asString("fakeplayer.command.move.forward.description")),
@ -311,7 +364,7 @@ public class CommandRegistry {
Usage.of("right", i18n.asString("fakeplayer.command.move.right.description")) Usage.of("right", i18n.asString("fakeplayer.command.move.right.description"))
) )
) )
.executes(MoveCommand.instance.move(1, 0)), .executes(moveCommand.move(1, 0)),
command("ride") command("ride")
.withPermission(Permission.ride) .withPermission(Permission.ride)
@ -319,19 +372,19 @@ public class CommandRegistry {
.withSubcommands( .withSubcommands(
command("me") command("me")
.withOptionalArguments(target("name")) .withOptionalArguments(target("name"))
.executesPlayer(RideCommand.instance::rideMe), .executesPlayer(rideCommand::rideMe),
command("target") command("target")
.withOptionalArguments(target("name")) .withOptionalArguments(target("name"))
.executes(RideCommand.instance::rideTarget), .executes(rideCommand::rideTarget),
command("anything") command("anything")
.withOptionalArguments(target("name")) .withOptionalArguments(target("name"))
.executes(RideCommand.instance::rideAnything), .executes(rideCommand::rideAnything),
command("vehicle") command("vehicle")
.withOptionalArguments(target("name")) .withOptionalArguments(target("name"))
.executes(RideCommand.instance::rideVehicle), .executes(rideCommand::rideVehicle),
command("stop") command("stop")
.withOptionalArguments(target("name")) .withOptionalArguments(target("name"))
.executes(RideCommand.instance::stopRiding), .executes(rideCommand::stopRiding),
helpCommand( helpCommand(
"/fp ride", "/fp ride",
Usage.of("me", i18n.asString("fakeplayer.command.ride.me.description")), Usage.of("me", i18n.asString("fakeplayer.command.ride.me.description")),
@ -345,17 +398,17 @@ public class CommandRegistry {
.withPermission(Permission.swap) .withPermission(Permission.swap)
.withRequirement(CommandSupports::hasTarget) .withRequirement(CommandSupports::hasTarget)
.withOptionalArguments(target("name")) .withOptionalArguments(target("name"))
.executes(SwapCommand.instance::swap), .executes(swapCommand::swap),
command("sleep") command("sleep")
.withPermission(Permission.sleep) .withPermission(Permission.sleep)
.withRequirement(CommandSupports::hasTarget) .withRequirement(CommandSupports::hasTarget)
.withOptionalArguments(target("name", p -> !p.isSleeping())) .withOptionalArguments(target("name", p -> !p.isSleeping()))
.executes(SleepCommand.instance::sleep), .executes(sleepCommand::sleep),
command("wakeup") command("wakeup")
.withPermission(Permission.wakeup) .withPermission(Permission.wakeup)
.withRequirement(CommandSupports::hasTarget) .withRequirement(CommandSupports::hasTarget)
.withOptionalArguments(target("name", LivingEntity::isSleeping)) .withOptionalArguments(target("name", LivingEntity::isSleeping))
.executes(SleepCommand.instance::wakeup), .executes(sleepCommand::wakeup),
command("cmd") command("cmd")
.withRequirement(CommandSupports::isCmdAvailable) .withRequirement(CommandSupports::isCmdAvailable)
@ -363,14 +416,14 @@ public class CommandRegistry {
target("name"), target("name"),
cmd("command") cmd("command")
) )
.executes(CmdCommand.instance::cmd), .executes(cmdCommand::cmd),
command("killall") command("killall")
.withPermission(CommandPermission.OP) .withPermission(CommandPermission.OP)
.executes(KillallCommand.instance::killall), .executes(killallCommand::killall),
command("reload") command("reload")
.withPermission(CommandPermission.OP) .withPermission(CommandPermission.OP)
.executes(ReloadCommand.instance::reload) .executes(reloadCommand::reload)
).register(); ).register();
} }

View File

@ -30,30 +30,32 @@ import static io.github.hello09x.bedrock.command.Commands.int32;
public abstract class CommandSupports { public abstract class CommandSupports {
private final static FakeplayerManager manager = FakeplayerManager.instance; private final static FakeplayerManager manager = Main.getInjector().getInstance(FakeplayerManager.class);
private final static FakeplayerConfig config = FakeplayerConfig.instance; private final static FakeplayerConfig config = Main.getInjector().getInstance(FakeplayerConfig.class);
private final static I18n i18n = Main.getI18n(); private final static I18n i18n = Main.getI18n();
private static final ActionCommand actionCommand = Main.getInjector().getInstance(ActionCommand.class);
public static @NotNull CommandAPICommand[] newActionCommands(@NotNull Action.ActionType action) { public static @NotNull CommandAPICommand[] newActionCommands(@NotNull Action.ActionType action) {
return new CommandAPICommand[]{ return new CommandAPICommand[]{
command("once") command("once")
.withOptionalArguments(target("name")) .withOptionalArguments(target("name"))
.executes(ActionCommand.instance.action(action, Action.ActionSetting.once())), .executes(actionCommand.action(action, Action.ActionSetting.once())),
command("continuous") command("continuous")
.withOptionalArguments(target("name")) .withOptionalArguments(target("name"))
.executes(ActionCommand.instance.action(action, Action.ActionSetting.continuous())), .executes(actionCommand.action(action, Action.ActionSetting.continuous())),
command("stop") command("stop")
.withOptionalArguments(target("name")) .withOptionalArguments(target("name"))
.executes(ActionCommand.instance.action(action, Action.ActionSetting.stop())), .executes(actionCommand.action(action, Action.ActionSetting.stop())),
command("interval") command("interval")
.withOptionalArguments( .withOptionalArguments(
int32("interval", 1), int32("interval", 1),
target("name")) target("name"))
.executes((sender, args) -> { .executes((sender, args) -> {
int interval = (int) args.getOptional("interval").orElse(1); int interval = (int) args.getOptional("interval").orElse(1);
ActionCommand.instance.action(sender, args, action, Action.ActionSetting.interval(interval)); actionCommand.action(sender, args, action, Action.ActionSetting.interval(interval));
}) })
}; };
} }

View File

@ -1,5 +1,6 @@
package io.github.hello09x.fakeplayer.core.command.impl; package io.github.hello09x.fakeplayer.core.command.impl;
import com.google.inject.Inject;
import dev.jorel.commandapi.CommandAPI; import dev.jorel.commandapi.CommandAPI;
import dev.jorel.commandapi.exceptions.WrapperCommandSyntaxException; import dev.jorel.commandapi.exceptions.WrapperCommandSyntaxException;
import dev.jorel.commandapi.executors.CommandArguments; import dev.jorel.commandapi.executors.CommandArguments;
@ -20,12 +21,20 @@ import java.util.logging.Logger;
public abstract class AbstractCommand { public abstract class AbstractCommand {
protected final static FakeplayerManager manager = FakeplayerManager.instance;
protected final static FakeplayerConfig config = FakeplayerConfig.instance;
protected final static NMSBridge bridge = Main.getBridge();
protected final static I18n i18n = Main.getI18n();
protected final static Logger log = Main.getInstance().getLogger(); protected final static Logger log = Main.getInstance().getLogger();
protected final I18n i18n = Main.getI18n();
@Inject
protected NMSBridge bridge;
@Inject
protected FakeplayerManager manager;
@Inject
protected FakeplayerConfig config;
protected @NotNull Player getTarget(@NotNull CommandSender sender, @NotNull CommandArguments args) throws WrapperCommandSyntaxException { protected @NotNull Player getTarget(@NotNull CommandSender sender, @NotNull CommandArguments args) throws WrapperCommandSyntaxException {
return this.getTarget(sender, args, null); return this.getTarget(sender, args, null);
} }

View File

@ -1,12 +1,12 @@
package io.github.hello09x.fakeplayer.core.command.impl; package io.github.hello09x.fakeplayer.core.command.impl;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import dev.jorel.commandapi.exceptions.WrapperCommandSyntaxException; import dev.jorel.commandapi.exceptions.WrapperCommandSyntaxException;
import dev.jorel.commandapi.executors.CommandArguments; import dev.jorel.commandapi.executors.CommandArguments;
import dev.jorel.commandapi.executors.CommandExecutor; import dev.jorel.commandapi.executors.CommandExecutor;
import io.github.hello09x.fakeplayer.api.spi.Action; import io.github.hello09x.fakeplayer.api.spi.Action;
import io.github.hello09x.fakeplayer.core.manager.action.ActionManager; import io.github.hello09x.fakeplayer.core.manager.action.ActionManager;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -15,12 +15,15 @@ import static net.kyori.adventure.text.Component.text;
import static net.kyori.adventure.text.format.NamedTextColor.GRAY; import static net.kyori.adventure.text.format.NamedTextColor.GRAY;
import static net.kyori.adventure.text.format.NamedTextColor.WHITE; import static net.kyori.adventure.text.format.NamedTextColor.WHITE;
@NoArgsConstructor(access = AccessLevel.PRIVATE) @Singleton
public class ActionCommand extends AbstractCommand { public class ActionCommand extends AbstractCommand {
public final static ActionCommand instance = new ActionCommand(); private final ActionManager actionManager;
private final ActionManager actionManager = ActionManager.instance; @Inject
public ActionCommand(ActionManager actionManager) {
this.actionManager = actionManager;
}
public @NotNull CommandExecutor action(@NotNull Action.ActionType action, @NotNull Action.ActionSetting setting) { public @NotNull CommandExecutor action(@NotNull Action.ActionType action, @NotNull Action.ActionSetting setting) {
return (sender, args) -> action(sender, args, action, setting.clone()); return (sender, args) -> action(sender, args, action, setting.clone());

View File

@ -1,5 +1,6 @@
package io.github.hello09x.fakeplayer.core.command.impl; package io.github.hello09x.fakeplayer.core.command.impl;
import com.google.inject.Singleton;
import dev.jorel.commandapi.CommandAPI; import dev.jorel.commandapi.CommandAPI;
import dev.jorel.commandapi.exceptions.WrapperCommandSyntaxException; import dev.jorel.commandapi.exceptions.WrapperCommandSyntaxException;
import dev.jorel.commandapi.executors.CommandArguments; import dev.jorel.commandapi.executors.CommandArguments;
@ -14,11 +15,9 @@ import java.util.Objects;
import static net.kyori.adventure.text.format.NamedTextColor.GRAY; import static net.kyori.adventure.text.format.NamedTextColor.GRAY;
@NoArgsConstructor(access = AccessLevel.PRIVATE) @Singleton
public class CmdCommand extends AbstractCommand { public class CmdCommand extends AbstractCommand {
public final static CmdCommand instance = new CmdCommand();
/** /**
* 假人执行命令 * 假人执行命令
*/ */

View File

@ -1,5 +1,7 @@
package io.github.hello09x.fakeplayer.core.command.impl; package io.github.hello09x.fakeplayer.core.command.impl;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import dev.jorel.commandapi.CommandAPI; import dev.jorel.commandapi.CommandAPI;
import dev.jorel.commandapi.exceptions.WrapperCommandSyntaxException; import dev.jorel.commandapi.exceptions.WrapperCommandSyntaxException;
import dev.jorel.commandapi.executors.CommandArguments; import dev.jorel.commandapi.executors.CommandArguments;
@ -27,12 +29,15 @@ import static net.kyori.adventure.text.event.ClickEvent.runCommand;
import static net.kyori.adventure.text.format.NamedTextColor.*; import static net.kyori.adventure.text.format.NamedTextColor.*;
import static net.kyori.adventure.text.format.TextDecoration.UNDERLINED; import static net.kyori.adventure.text.format.TextDecoration.UNDERLINED;
@NoArgsConstructor(access = AccessLevel.PRIVATE) @Singleton
public class ConfigCommand extends AbstractCommand { public class ConfigCommand extends AbstractCommand {
public final static ConfigCommand instance = new ConfigCommand(); private final UserConfigManager configManager;
private final UserConfigManager configManager = UserConfigManager.instance; @Inject
public ConfigCommand(UserConfigManager configManager) {
this.configManager = configManager;
}
/** /**
* 设置配置 * 设置配置

View File

@ -1,5 +1,6 @@
package io.github.hello09x.fakeplayer.core.command.impl; package io.github.hello09x.fakeplayer.core.command.impl;
import com.google.inject.Singleton;
import dev.jorel.commandapi.exceptions.WrapperCommandSyntaxException; import dev.jorel.commandapi.exceptions.WrapperCommandSyntaxException;
import dev.jorel.commandapi.executors.CommandArguments; import dev.jorel.commandapi.executors.CommandArguments;
import io.github.hello09x.fakeplayer.core.util.Mth; import io.github.hello09x.fakeplayer.core.util.Mth;
@ -16,11 +17,9 @@ import static net.kyori.adventure.text.Component.*;
import static net.kyori.adventure.text.format.NamedTextColor.GRAY; import static net.kyori.adventure.text.format.NamedTextColor.GRAY;
import static net.kyori.adventure.text.format.NamedTextColor.WHITE; import static net.kyori.adventure.text.format.NamedTextColor.WHITE;
@NoArgsConstructor(access = AccessLevel.PRIVATE) @Singleton
public class DistanceCommand extends AbstractCommand { public class DistanceCommand extends AbstractCommand {
public final static DistanceCommand instance = new DistanceCommand();
/** /**
* 查看距离 * 查看距离
*/ */

View File

@ -1,6 +1,7 @@
package io.github.hello09x.fakeplayer.core.command.impl; package io.github.hello09x.fakeplayer.core.command.impl;
import com.google.inject.Singleton;
import dev.jorel.commandapi.exceptions.WrapperCommandSyntaxException; import dev.jorel.commandapi.exceptions.WrapperCommandSyntaxException;
import dev.jorel.commandapi.executors.CommandArguments; import dev.jorel.commandapi.executors.CommandArguments;
import io.github.hello09x.bedrock.io.Experiences; import io.github.hello09x.bedrock.io.Experiences;
@ -13,12 +14,9 @@ import org.jetbrains.annotations.NotNull;
import static net.kyori.adventure.text.Component.text; import static net.kyori.adventure.text.Component.text;
import static net.kyori.adventure.text.format.NamedTextColor.*; import static net.kyori.adventure.text.format.NamedTextColor.*;
@NoArgsConstructor(access = AccessLevel.PRIVATE) @Singleton
public class ExpmeCommand extends AbstractCommand { public class ExpmeCommand extends AbstractCommand {
public final static ExpmeCommand instance = new ExpmeCommand();
public void expme(@NotNull Player sender, @NotNull CommandArguments args) throws WrapperCommandSyntaxException { public void expme(@NotNull Player sender, @NotNull CommandArguments args) throws WrapperCommandSyntaxException {
var target = getTarget(sender, args); var target = getTarget(sender, args);
var exp = Experiences.getExp(target); var exp = Experiences.getExp(target);

View File

@ -1,5 +1,6 @@
package io.github.hello09x.fakeplayer.core.command.impl; package io.github.hello09x.fakeplayer.core.command.impl;
import com.google.inject.Singleton;
import dev.jorel.commandapi.exceptions.WrapperCommandSyntaxException; import dev.jorel.commandapi.exceptions.WrapperCommandSyntaxException;
import dev.jorel.commandapi.executors.CommandArguments; import dev.jorel.commandapi.executors.CommandArguments;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
@ -8,11 +9,9 @@ import org.jetbrains.annotations.NotNull;
import java.util.Objects; import java.util.Objects;
@NoArgsConstructor @Singleton
public class HoldCommand extends AbstractCommand { public class HoldCommand extends AbstractCommand {
public final static HoldCommand instance = new HoldCommand();
public void hold(@NotNull CommandSender sender, @NotNull CommandArguments args) throws WrapperCommandSyntaxException { public void hold(@NotNull CommandSender sender, @NotNull CommandArguments args) throws WrapperCommandSyntaxException {
var target = super.getTarget(sender, args); var target = super.getTarget(sender, args);
var slot = (int) Objects.requireNonNull(args.get("slot")); var slot = (int) Objects.requireNonNull(args.get("slot"));

View File

@ -1,5 +1,6 @@
package io.github.hello09x.fakeplayer.core.command.impl; package io.github.hello09x.fakeplayer.core.command.impl;
import com.google.inject.Singleton;
import dev.jorel.commandapi.CommandAPI; import dev.jorel.commandapi.CommandAPI;
import dev.jorel.commandapi.exceptions.WrapperCommandSyntaxException; import dev.jorel.commandapi.exceptions.WrapperCommandSyntaxException;
import dev.jorel.commandapi.executors.CommandArguments; import dev.jorel.commandapi.executors.CommandArguments;
@ -10,10 +11,9 @@ import org.jetbrains.annotations.NotNull;
import java.util.Objects; import java.util.Objects;
@NoArgsConstructor(access = AccessLevel.PRIVATE) @Singleton
public class InvseeCommand extends AbstractCommand { public class InvseeCommand extends AbstractCommand {
public final static InvseeCommand instance = new InvseeCommand();
/** /**
* 查看背包 * 查看背包

View File

@ -1,5 +1,6 @@
package io.github.hello09x.fakeplayer.core.command.impl; package io.github.hello09x.fakeplayer.core.command.impl;
import com.google.inject.Singleton;
import dev.jorel.commandapi.exceptions.WrapperCommandSyntaxException; import dev.jorel.commandapi.exceptions.WrapperCommandSyntaxException;
import dev.jorel.commandapi.executors.CommandArguments; import dev.jorel.commandapi.executors.CommandArguments;
import lombok.AccessLevel; import lombok.AccessLevel;
@ -12,11 +13,9 @@ import java.util.StringJoiner;
import static net.kyori.adventure.text.Component.*; import static net.kyori.adventure.text.Component.*;
import static net.kyori.adventure.text.format.NamedTextColor.GRAY; import static net.kyori.adventure.text.format.NamedTextColor.GRAY;
@NoArgsConstructor(access = AccessLevel.PRIVATE) @Singleton
public class KillCommand extends AbstractCommand { public class KillCommand extends AbstractCommand {
public final static KillCommand instance = new KillCommand();
/** /**
* 移除假人 * 移除假人
*/ */

View File

@ -1,16 +1,15 @@
package io.github.hello09x.fakeplayer.core.command.impl; package io.github.hello09x.fakeplayer.core.command.impl;
import com.google.inject.Singleton;
import dev.jorel.commandapi.executors.CommandArguments; import dev.jorel.commandapi.executors.CommandArguments;
import lombok.AccessLevel; import lombok.AccessLevel;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@NoArgsConstructor(access = AccessLevel.PRIVATE) @Singleton
public class KillallCommand extends AbstractCommand { public class KillallCommand extends AbstractCommand {
public final static KillallCommand instance = new KillallCommand();
/** /**
* 移除服务器所有假人 * 移除服务器所有假人
*/ */

View File

@ -1,5 +1,6 @@
package io.github.hello09x.fakeplayer.core.command.impl; package io.github.hello09x.fakeplayer.core.command.impl;
import com.google.inject.Singleton;
import dev.jorel.commandapi.executors.CommandArguments; import dev.jorel.commandapi.executors.CommandArguments;
import io.github.hello09x.bedrock.page.Page; import io.github.hello09x.bedrock.page.Page;
import io.github.hello09x.fakeplayer.core.command.Permission; import io.github.hello09x.fakeplayer.core.command.Permission;
@ -17,10 +18,9 @@ import static net.kyori.adventure.text.event.ClickEvent.runCommand;
import static net.kyori.adventure.text.format.NamedTextColor.*; import static net.kyori.adventure.text.format.NamedTextColor.*;
import static net.kyori.adventure.text.format.TextDecoration.BOLD; import static net.kyori.adventure.text.format.TextDecoration.BOLD;
@NoArgsConstructor(access = AccessLevel.PRIVATE) @Singleton
public class ListCommand extends AbstractCommand { public class ListCommand extends AbstractCommand {
public final static ListCommand instance = new ListCommand();
private static String toLocationString(@NotNull Location location) { private static String toLocationString(@NotNull Location location) {
return location.getWorld().getName() return location.getWorld().getName()

View File

@ -1,14 +1,13 @@
package io.github.hello09x.fakeplayer.core.command.impl; package io.github.hello09x.fakeplayer.core.command.impl;
import com.google.inject.Singleton;
import dev.jorel.commandapi.executors.CommandExecutor; import dev.jorel.commandapi.executors.CommandExecutor;
import lombok.AccessLevel; import lombok.AccessLevel;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
@NoArgsConstructor(access = AccessLevel.PRIVATE) @Singleton
public class MoveCommand extends AbstractCommand { public class MoveCommand extends AbstractCommand {
public final static MoveCommand instance = new MoveCommand();
/** /**
* 假人移动 * 假人移动
*/ */

View File

@ -1,5 +1,7 @@
package io.github.hello09x.fakeplayer.core.command.impl; package io.github.hello09x.fakeplayer.core.command.impl;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import dev.jorel.commandapi.executors.CommandArguments; import dev.jorel.commandapi.executors.CommandArguments;
import io.github.hello09x.fakeplayer.core.config.FakeplayerConfig; import io.github.hello09x.fakeplayer.core.config.FakeplayerConfig;
import lombok.AccessLevel; import lombok.AccessLevel;
@ -9,12 +11,15 @@ import org.jetbrains.annotations.NotNull;
import static net.kyori.adventure.text.format.NamedTextColor.GRAY; import static net.kyori.adventure.text.format.NamedTextColor.GRAY;
@NoArgsConstructor(access = AccessLevel.PRIVATE) @Singleton
public class ReloadCommand extends AbstractCommand { public class ReloadCommand extends AbstractCommand {
public final static ReloadCommand instance = new ReloadCommand(); private final FakeplayerConfig config;
private final FakeplayerConfig config = FakeplayerConfig.instance; @Inject
public ReloadCommand(FakeplayerConfig config) {
this.config = config;
}
public void reload(@NotNull CommandSender sender, @NotNull CommandArguments args) { public void reload(@NotNull CommandSender sender, @NotNull CommandArguments args) {
config.reload(true); config.reload(true);

View File

@ -1,5 +1,6 @@
package io.github.hello09x.fakeplayer.core.command.impl; package io.github.hello09x.fakeplayer.core.command.impl;
import com.google.inject.Singleton;
import dev.jorel.commandapi.exceptions.WrapperCommandSyntaxException; import dev.jorel.commandapi.exceptions.WrapperCommandSyntaxException;
import dev.jorel.commandapi.executors.CommandArguments; import dev.jorel.commandapi.executors.CommandArguments;
import lombok.AccessLevel; import lombok.AccessLevel;
@ -8,11 +9,9 @@ import org.bukkit.command.CommandSender;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@NoArgsConstructor(access = AccessLevel.PRIVATE) @Singleton
public class RespawnCommand extends AbstractCommand { public class RespawnCommand extends AbstractCommand {
public final static RespawnCommand instance = new RespawnCommand();
/** /**
* 重生 * 重生
*/ */

View File

@ -1,5 +1,6 @@
package io.github.hello09x.fakeplayer.core.command.impl; package io.github.hello09x.fakeplayer.core.command.impl;
import com.google.inject.Singleton;
import dev.jorel.commandapi.CommandAPI; import dev.jorel.commandapi.CommandAPI;
import dev.jorel.commandapi.exceptions.WrapperCommandSyntaxException; import dev.jorel.commandapi.exceptions.WrapperCommandSyntaxException;
import dev.jorel.commandapi.executors.CommandArguments; import dev.jorel.commandapi.executors.CommandArguments;
@ -18,11 +19,9 @@ import static net.kyori.adventure.text.Component.text;
import static net.kyori.adventure.text.format.NamedTextColor.GRAY; import static net.kyori.adventure.text.format.NamedTextColor.GRAY;
import static net.kyori.adventure.text.format.NamedTextColor.WHITE; import static net.kyori.adventure.text.format.NamedTextColor.WHITE;
@NoArgsConstructor(access = AccessLevel.PRIVATE) @Singleton
public class RideCommand extends AbstractCommand { public class RideCommand extends AbstractCommand {
public final static RideCommand instance = new RideCommand();
/** /**
* 骑最近的实体 * 骑最近的实体
*/ */

View File

@ -1,5 +1,6 @@
package io.github.hello09x.fakeplayer.core.command.impl; package io.github.hello09x.fakeplayer.core.command.impl;
import com.google.inject.Singleton;
import dev.jorel.commandapi.exceptions.WrapperCommandSyntaxException; import dev.jorel.commandapi.exceptions.WrapperCommandSyntaxException;
import dev.jorel.commandapi.executors.CommandArguments; import dev.jorel.commandapi.executors.CommandArguments;
import dev.jorel.commandapi.executors.CommandExecutor; import dev.jorel.commandapi.executors.CommandExecutor;
@ -7,8 +8,6 @@ import dev.jorel.commandapi.wrappers.Rotation;
import io.github.hello09x.fakeplayer.core.constant.Direction; import io.github.hello09x.fakeplayer.core.constant.Direction;
import io.github.hello09x.fakeplayer.core.util.Mth; import io.github.hello09x.fakeplayer.core.util.Mth;
import io.papermc.paper.entity.LookAnchor; import io.papermc.paper.entity.LookAnchor;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@ -16,12 +15,9 @@ import org.jetbrains.annotations.NotNull;
import java.util.Objects; import java.util.Objects;
@Singleton
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class RotationCommand extends AbstractCommand { public class RotationCommand extends AbstractCommand {
public final static RotationCommand instance = new RotationCommand();
/** /**
* 看向给定坐标 * 看向给定坐标
*/ */

View File

@ -1,5 +1,6 @@
package io.github.hello09x.fakeplayer.core.command.impl; package io.github.hello09x.fakeplayer.core.command.impl;
import com.google.inject.Singleton;
import dev.jorel.commandapi.executors.CommandArguments; import dev.jorel.commandapi.executors.CommandArguments;
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@ -9,10 +10,9 @@ import static net.kyori.adventure.text.Component.text;
import static net.kyori.adventure.text.format.NamedTextColor.GRAY; import static net.kyori.adventure.text.format.NamedTextColor.GRAY;
import static net.kyori.adventure.text.format.NamedTextColor.WHITE; import static net.kyori.adventure.text.format.NamedTextColor.WHITE;
@Singleton
public class SelectCommand extends AbstractCommand { public class SelectCommand extends AbstractCommand {
public final static SelectCommand instance = new SelectCommand();
public void select(@NotNull Player sender, @NotNull CommandArguments args) { public void select(@NotNull Player sender, @NotNull CommandArguments args) {
var target = this.getTargetNullable(sender, args); var target = this.getTargetNullable(sender, args);
manager.setSelection(sender, target); manager.setSelection(sender, target);

View File

@ -1,5 +1,6 @@
package io.github.hello09x.fakeplayer.core.command.impl; package io.github.hello09x.fakeplayer.core.command.impl;
import com.google.inject.Singleton;
import dev.jorel.commandapi.CommandAPI; import dev.jorel.commandapi.CommandAPI;
import dev.jorel.commandapi.exceptions.WrapperCommandSyntaxException; import dev.jorel.commandapi.exceptions.WrapperCommandSyntaxException;
import dev.jorel.commandapi.executors.CommandArguments; import dev.jorel.commandapi.executors.CommandArguments;
@ -15,11 +16,9 @@ import java.util.Objects;
import static net.kyori.adventure.text.Component.text; import static net.kyori.adventure.text.Component.text;
import static net.kyori.adventure.text.format.NamedTextColor.*; import static net.kyori.adventure.text.format.NamedTextColor.*;
@NoArgsConstructor(access = AccessLevel.PRIVATE) @Singleton
public class SetCommand extends AbstractCommand { public class SetCommand extends AbstractCommand {
public final static SetCommand instance = new SetCommand();
public void set(@NotNull CommandSender sender, @NotNull CommandArguments args) throws WrapperCommandSyntaxException { public void set(@NotNull CommandSender sender, @NotNull CommandArguments args) throws WrapperCommandSyntaxException {
var target = super.getTarget(sender, args); var target = super.getTarget(sender, args);

View File

@ -1,5 +1,6 @@
package io.github.hello09x.fakeplayer.core.command.impl; package io.github.hello09x.fakeplayer.core.command.impl;
import com.google.inject.Singleton;
import dev.jorel.commandapi.exceptions.WrapperCommandSyntaxException; import dev.jorel.commandapi.exceptions.WrapperCommandSyntaxException;
import dev.jorel.commandapi.executors.CommandArguments; import dev.jorel.commandapi.executors.CommandArguments;
import io.github.hello09x.fakeplayer.core.Main; import io.github.hello09x.fakeplayer.core.Main;
@ -16,13 +17,12 @@ import java.util.Objects;
import static net.kyori.adventure.text.format.NamedTextColor.RED; import static net.kyori.adventure.text.format.NamedTextColor.RED;
@Singleton
public class SkinCommand extends AbstractCommand { public class SkinCommand extends AbstractCommand {
public final static SkinCommand instance = new SkinCommand();
private final Map<CommandSender, MutableInt> spams = new HashMap<>(); private final Map<CommandSender, MutableInt> spams = new HashMap<>();
private SkinCommand() { public SkinCommand() {
Bukkit.getScheduler().runTaskTimer(Main.getInstance(), () -> { Bukkit.getScheduler().runTaskTimer(Main.getInstance(), () -> {
spams.entrySet().removeIf(counter -> counter.getValue().decrementAndGet() <= 0); spams.entrySet().removeIf(counter -> counter.getValue().decrementAndGet() <= 0);
}, 0, 1); }, 0, 1);

View File

@ -1,5 +1,6 @@
package io.github.hello09x.fakeplayer.core.command.impl; package io.github.hello09x.fakeplayer.core.command.impl;
import com.google.inject.Singleton;
import dev.jorel.commandapi.exceptions.WrapperCommandSyntaxException; import dev.jorel.commandapi.exceptions.WrapperCommandSyntaxException;
import dev.jorel.commandapi.executors.CommandArguments; import dev.jorel.commandapi.executors.CommandArguments;
import io.github.hello09x.bedrock.util.Blocks; import io.github.hello09x.bedrock.util.Blocks;
@ -9,11 +10,9 @@ import org.bukkit.block.data.type.Bed;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@NoArgsConstructor(access = AccessLevel.PRIVATE) @Singleton
public class SleepCommand extends AbstractCommand { public class SleepCommand extends AbstractCommand {
public final static SleepCommand instance = new SleepCommand();
/** /**
* 睡觉 * 睡觉
*/ */

View File

@ -1,5 +1,6 @@
package io.github.hello09x.fakeplayer.core.command.impl; package io.github.hello09x.fakeplayer.core.command.impl;
import com.google.inject.Singleton;
import dev.jorel.commandapi.exceptions.WrapperCommandSyntaxException; import dev.jorel.commandapi.exceptions.WrapperCommandSyntaxException;
import dev.jorel.commandapi.executors.CommandArguments; import dev.jorel.commandapi.executors.CommandArguments;
import lombok.AccessLevel; import lombok.AccessLevel;
@ -7,11 +8,9 @@ import lombok.NoArgsConstructor;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@NoArgsConstructor(access = AccessLevel.PRIVATE) @Singleton
public class SneakCommand extends AbstractCommand { public class SneakCommand extends AbstractCommand {
public final static SneakCommand instance = new SneakCommand();
/** /**
* 设置潜行 * 设置潜行
*/ */

View File

@ -1,6 +1,7 @@
package io.github.hello09x.fakeplayer.core.command.impl; package io.github.hello09x.fakeplayer.core.command.impl;
import com.google.common.base.Throwables; import com.google.common.base.Throwables;
import com.google.inject.Singleton;
import dev.jorel.commandapi.executors.CommandArguments; import dev.jorel.commandapi.executors.CommandArguments;
import io.github.hello09x.bedrock.command.MessageException; import io.github.hello09x.bedrock.command.MessageException;
import io.github.hello09x.fakeplayer.core.Main; import io.github.hello09x.fakeplayer.core.Main;
@ -25,11 +26,9 @@ import java.util.Optional;
import static net.kyori.adventure.text.Component.text; import static net.kyori.adventure.text.Component.text;
import static net.kyori.adventure.text.format.NamedTextColor.*; import static net.kyori.adventure.text.format.NamedTextColor.*;
@NoArgsConstructor(access = AccessLevel.PRIVATE) @Singleton
public class SpawnCommand extends AbstractCommand { public class SpawnCommand extends AbstractCommand {
public final static SpawnCommand instance = new SpawnCommand();
private final static DateTimeFormatter REMOVE_AT_FORMATTER = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm"); private final static DateTimeFormatter REMOVE_AT_FORMATTER = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm");
private static String toLocationString(@NotNull Location location) { private static String toLocationString(@NotNull Location location) {

View File

@ -1,5 +1,6 @@
package io.github.hello09x.fakeplayer.core.command.impl; package io.github.hello09x.fakeplayer.core.command.impl;
import com.google.inject.Singleton;
import dev.jorel.commandapi.exceptions.WrapperCommandSyntaxException; import dev.jorel.commandapi.exceptions.WrapperCommandSyntaxException;
import dev.jorel.commandapi.executors.CommandArguments; import dev.jorel.commandapi.executors.CommandArguments;
import io.github.hello09x.bedrock.io.Experiences; import io.github.hello09x.bedrock.io.Experiences;
@ -30,11 +31,9 @@ import static net.kyori.adventure.text.event.ClickEvent.runCommand;
import static net.kyori.adventure.text.format.NamedTextColor.*; import static net.kyori.adventure.text.format.NamedTextColor.*;
import static net.kyori.adventure.text.format.TextDecoration.UNDERLINED; import static net.kyori.adventure.text.format.TextDecoration.UNDERLINED;
@NoArgsConstructor(access = AccessLevel.PRIVATE) @Singleton
public class StatusCommand extends AbstractCommand { public class StatusCommand extends AbstractCommand {
public final static StatusCommand instance = new StatusCommand();
private final static Component LINE_SPLITTER = text(StringUtils.repeat("-", 20), GRAY); private final static Component LINE_SPLITTER = text(StringUtils.repeat("-", 20), GRAY);
private static @NotNull NamedTextColor color(double current, double max) { private static @NotNull NamedTextColor color(double current, double max) {

View File

@ -1,16 +1,15 @@
package io.github.hello09x.fakeplayer.core.command.impl; package io.github.hello09x.fakeplayer.core.command.impl;
import com.google.inject.Singleton;
import dev.jorel.commandapi.exceptions.WrapperCommandSyntaxException; import dev.jorel.commandapi.exceptions.WrapperCommandSyntaxException;
import dev.jorel.commandapi.executors.CommandArguments; import dev.jorel.commandapi.executors.CommandArguments;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@NoArgsConstructor @Singleton
public class SwapCommand extends AbstractCommand { public class SwapCommand extends AbstractCommand {
public final static SwapCommand instance = new SwapCommand();
/** /**
* 交换主副手物品 * 交换主副手物品
*/ */

View File

@ -1,5 +1,6 @@
package io.github.hello09x.fakeplayer.core.command.impl; package io.github.hello09x.fakeplayer.core.command.impl;
import com.google.inject.Singleton;
import dev.jorel.commandapi.exceptions.WrapperCommandSyntaxException; import dev.jorel.commandapi.exceptions.WrapperCommandSyntaxException;
import dev.jorel.commandapi.executors.CommandArguments; import dev.jorel.commandapi.executors.CommandArguments;
import io.github.hello09x.bedrock.util.Teleportor; import io.github.hello09x.bedrock.util.Teleportor;
@ -11,11 +12,9 @@ import org.jetbrains.annotations.NotNull;
import static net.kyori.adventure.text.format.NamedTextColor.RED; import static net.kyori.adventure.text.format.NamedTextColor.RED;
@NoArgsConstructor(access = AccessLevel.PRIVATE) @Singleton
public class TeleportCommand extends AbstractCommand { public class TeleportCommand extends AbstractCommand {
public final static TeleportCommand instance = new TeleportCommand();
/** /**
* 传送到假人 * 传送到假人
*/ */

View File

@ -36,7 +36,6 @@ public class FakeplayerConfig extends Config<FakeplayerConfig> {
); );
} }
/** /**
* 每位玩家最多多少个假人 * 每位玩家最多多少个假人
*/ */
@ -146,10 +145,10 @@ public class FakeplayerConfig extends Config<FakeplayerConfig> {
this.nameTemplate = getNameTemplate(file); this.nameTemplate = getNameTemplate(file);
this.lifespan = getLifespan(file); this.lifespan = getLifespan(file);
this.allowCommands = file.getStringList("allow-commands") this.allowCommands = file.getStringList("allow-commands")
.stream() .stream()
.map(c -> c.startsWith("/") ? c.substring(1) : c) .map(c -> c.startsWith("/") ? c.substring(1) : c)
.filter(c -> !c.isBlank()) .filter(c -> !c.isBlank())
.collect(Collectors.toSet()); .collect(Collectors.toSet());
} }
private @Nullable Duration getLifespan(@NotNull FileConfiguration file) { private @Nullable Duration getLifespan(@NotNull FileConfiguration file) {
@ -164,7 +163,7 @@ public class FakeplayerConfig extends Config<FakeplayerConfig> {
private @NotNull Pattern getNamePattern(@NotNull FileConfiguration file) { private @NotNull Pattern getNamePattern(@NotNull FileConfiguration file) {
try { try {
return Pattern.compile(file.getString("name-pattern", defaultNameChars)); return Pattern.compile(file.getString("name-pattern", defaultNameChars));
} catch (PatternSyntaxException e) { } catch(PatternSyntaxException e) {
log.warning("Invalid name-pattern: " + file.getString("name-chars")); log.warning("Invalid name-pattern: " + file.getString("name-chars"));
return Pattern.compile(defaultNameChars); return Pattern.compile(defaultNameChars);
} }

View File

@ -40,11 +40,11 @@ public class FakePlayer {
private final static InternalAddressGenerator ipGen = new InternalAddressGenerator(); private final static InternalAddressGenerator ipGen = new InternalAddressGenerator();
private final static FakeplayerConfig config = FakeplayerConfig.instance; private final static FakeplayerConfig config = Main.getInjector().getInstance(FakeplayerConfig.class);
private final static I18n i18n = Main.getI18n(); private final static I18n i18n = Main.getI18n();
private final static NMSBridge bridge = Main.getBridge(); private final static NMSBridge bridge = Main.getInjector().getInstance(NMSBridge.class);
@NotNull @NotNull
@Getter @Getter
@ -158,13 +158,13 @@ public class FakePlayer {
this.player.setCollidable(option.collidable()); this.player.setCollidable(option.collidable());
this.player.setCanPickupItems(option.pickupItems()); this.player.setCanPickupItems(option.pickupItems());
if (option.lookAtEntity()) { if (option.lookAtEntity()) {
ActionManager.instance.setAction(player, Action.ActionType.LOOK_AT_NEAREST_ENTITY, Action.ActionSetting.continuous()); Main.getInjector().getInstance(ActionManager.class).setAction(player, Action.ActionType.LOOK_AT_NEAREST_ENTITY, Action.ActionSetting.continuous());
} }
if (option.skin() && this.creator instanceof Player playerCreator) { if (option.skin() && this.creator instanceof Player playerCreator) {
Skins.copySkin(playerCreator, this.player); Skins.copySkin(playerCreator, this.player);
} }
if (option.replenish()) { if (option.replenish()) {
FakeplayerManager.instance.setReplenish(player, true); Main.getInjector().getInstance(FakeplayerManager.class).setReplenish(player, true);
} }
this.network = bridge.createNetwork(address); this.network = bridge.createNetwork(address);

View File

@ -1,6 +1,7 @@
package io.github.hello09x.fakeplayer.core.entity; package io.github.hello09x.fakeplayer.core.entity;
import io.github.hello09x.fakeplayer.api.spi.NMSServerPlayer; import io.github.hello09x.fakeplayer.api.spi.NMSServerPlayer;
import io.github.hello09x.fakeplayer.core.Main;
import io.github.hello09x.fakeplayer.core.manager.FakeplayerManager; import io.github.hello09x.fakeplayer.core.manager.FakeplayerManager;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.scheduler.BukkitRunnable;
@ -8,8 +9,6 @@ import org.jetbrains.annotations.NotNull;
public class FakeplayerTicker extends BukkitRunnable { public class FakeplayerTicker extends BukkitRunnable {
private final static FakeplayerManager manager = FakeplayerManager.instance;
public final static long NO_REMOVE_AT = -1; public final static long NO_REMOVE_AT = -1;
@NotNull @NotNull
@ -43,7 +42,7 @@ public class FakeplayerTicker extends BukkitRunnable {
} }
if (this.removeAt != NO_REMOVE_AT && this.player.getTickCount() % 20 == 0 && System.currentTimeMillis() > removeAt) { if (this.removeAt != NO_REMOVE_AT && this.player.getTickCount() % 20 == 0 && System.currentTimeMillis() > removeAt) {
manager.remove(player.getName(), "lifespan ends"); Main.getInjector().getInstance(FakeplayerManager.class).remove(player.getName(), "lifespan ends");
super.cancel(); super.cancel();
return; return;
} }

View File

@ -1,5 +1,6 @@
package io.github.hello09x.fakeplayer.core.entity.action; package io.github.hello09x.fakeplayer.core.entity.action;
import com.google.inject.Inject;
import io.github.hello09x.fakeplayer.api.spi.Action; import io.github.hello09x.fakeplayer.api.spi.Action;
import io.github.hello09x.fakeplayer.api.spi.ActionTicker; import io.github.hello09x.fakeplayer.api.spi.ActionTicker;
import io.github.hello09x.fakeplayer.api.spi.NMSBridge; import io.github.hello09x.fakeplayer.api.spi.NMSBridge;
@ -8,11 +9,9 @@ import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.UnknownNullability; import org.jetbrains.annotations.UnknownNullability;
import java.util.Objects;
public abstract class BaseActionTicker implements ActionTicker { public abstract class BaseActionTicker implements ActionTicker {
protected final static NMSBridge bridge = Objects.requireNonNull(NMSBridge.getInstance(), "Unsupported"); protected final NMSBridge bridge;
/** /**
* 这个类无法初始化的动作, 由子类完成 * 这个类无法初始化的动作, 由子类完成
@ -23,14 +22,15 @@ public abstract class BaseActionTicker implements ActionTicker {
@NotNull @NotNull
protected Action.ActionSetting setting; protected Action.ActionSetting setting;
public BaseActionTicker(@NotNull Player player, @NotNull Action.ActionType action, @NotNull Action.ActionSetting setting) { public BaseActionTicker(NMSBridge nms, @NotNull Player player, @NotNull Action.ActionType action, @NotNull Action.ActionSetting setting) {
this.bridge = nms;
this.setting = setting; this.setting = setting;
this.action = switch (action) { this.action = switch (action) {
case JUMP -> new JumpAction(bridge.fromPlayer(player)); case JUMP -> new JumpAction(nms.fromPlayer(player));
case LOOK_AT_NEAREST_ENTITY -> new LookAtEntityAction(bridge.fromPlayer(player)); case LOOK_AT_NEAREST_ENTITY -> new LookAtEntityAction(nms.fromPlayer(player));
case DROP_ITEM -> new DropItemAction(bridge.fromPlayer(player)); case DROP_ITEM -> new DropItemAction(nms.fromPlayer(player));
case DROP_STACK -> new DropStackAction(bridge.fromPlayer(player)); case DROP_STACK -> new DropStackAction(nms.fromPlayer(player));
case DROP_INVENTORY -> new DropInventoryAction(bridge.fromPlayer(player)); case DROP_INVENTORY -> new DropInventoryAction(nms.fromPlayer(player));
default -> null; // 子类需要实现其他 Action default -> null; // 子类需要实现其他 Action
}; };
} }

View File

@ -1,6 +1,8 @@
package io.github.hello09x.fakeplayer.core.listener; package io.github.hello09x.fakeplayer.core.listener;
import com.google.common.base.Throwables; import com.google.common.base.Throwables;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import io.github.hello09x.bedrock.i18n.I18n; import io.github.hello09x.bedrock.i18n.I18n;
import io.github.hello09x.fakeplayer.core.Main; import io.github.hello09x.fakeplayer.core.Main;
import io.github.hello09x.fakeplayer.core.config.FakeplayerConfig; import io.github.hello09x.fakeplayer.core.config.FakeplayerConfig;
@ -25,16 +27,24 @@ import java.util.logging.Logger;
import static net.kyori.adventure.text.Component.*; import static net.kyori.adventure.text.Component.*;
import static net.kyori.adventure.text.format.NamedTextColor.GRAY; import static net.kyori.adventure.text.format.NamedTextColor.GRAY;
@Singleton
public class FakeplayerListener implements Listener { public class FakeplayerListener implements Listener {
public final static FakeplayerListener instance = new FakeplayerListener();
private final static Logger log = Main.getInstance().getLogger(); private final static Logger log = Main.getInstance().getLogger();
private final FakeplayerManager manager = FakeplayerManager.instance;
private final FakeplayerConfig config = FakeplayerConfig.instance; private final FakeplayerManager manager;
private final UsedIdRepository usedIdRepository = UsedIdRepository.instance; private final UsedIdRepository usedIdRepository;
private final FakeplayerConfig config;
private final I18n i18n = Main.getI18n(); private final I18n i18n = Main.getI18n();
@Inject
public FakeplayerListener(FakeplayerManager manager, UsedIdRepository usedIdRepository, FakeplayerConfig config) {
this.manager = manager;
this.usedIdRepository = usedIdRepository;
this.config = config;
}
/** /**
* 拒绝真实玩家使用假人用过的 ID 登陆 * 拒绝真实玩家使用假人用过的 ID 登陆
*/ */

View File

@ -1,5 +1,7 @@
package io.github.hello09x.fakeplayer.core.listener; package io.github.hello09x.fakeplayer.core.listener;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import io.github.hello09x.fakeplayer.core.manager.FakeplayerManager; import io.github.hello09x.fakeplayer.core.manager.FakeplayerManager;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
@ -11,10 +13,15 @@ import org.bukkit.event.player.PlayerInteractAtEntityEvent;
import org.bukkit.event.player.PlayerToggleSneakEvent; import org.bukkit.event.player.PlayerToggleSneakEvent;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@Singleton
public class PlayerListeners implements Listener { public class PlayerListeners implements Listener {
public final static PlayerListeners instance = new PlayerListeners(); private final FakeplayerManager manager;
private final FakeplayerManager manager = FakeplayerManager.instance;
@Inject
public PlayerListeners(FakeplayerManager manager) {
this.manager = manager;
}
/** /**
* 玩家蹲伏时取消假人骑乘 * 玩家蹲伏时取消假人骑乘

View File

@ -2,6 +2,8 @@ package io.github.hello09x.fakeplayer.core.listener;
import com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent; import com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import io.github.hello09x.bedrock.util.Blocks; import io.github.hello09x.bedrock.util.Blocks;
import io.github.hello09x.fakeplayer.core.Main; import io.github.hello09x.fakeplayer.core.Main;
import io.github.hello09x.fakeplayer.core.command.Permission; import io.github.hello09x.fakeplayer.core.command.Permission;
@ -28,12 +30,15 @@ import org.jetbrains.annotations.Nullable;
import java.util.Optional; import java.util.Optional;
@Singleton
public class ReplenishListener implements Listener { public class ReplenishListener implements Listener {
public final static ReplenishListener instance = new ReplenishListener(); private final FakeplayerManager manager;
private final FakeplayerManager manager = FakeplayerManager.instance; @Inject
private final FakeplayerConfig config = FakeplayerConfig.instance; public ReplenishListener(FakeplayerManager manager) {
this.manager = manager;
}
/** /**
* 消耗物品自动填装 * 消耗物品自动填装

View File

@ -1,5 +1,6 @@
package io.github.hello09x.fakeplayer.core.manager; package io.github.hello09x.fakeplayer.core.manager;
import com.google.inject.Singleton;
import io.github.hello09x.fakeplayer.core.entity.FakePlayer; import io.github.hello09x.fakeplayer.core.entity.FakePlayer;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@ -8,10 +9,9 @@ import org.jetbrains.annotations.Unmodifiable;
import java.util.*; import java.util.*;
import java.util.stream.Stream; import java.util.stream.Stream;
@Singleton
public class FakeplayerList { public class FakeplayerList {
public final static FakeplayerList instance = new FakeplayerList();
private final Map<String, FakePlayer> playersByName = new HashMap<>(); private final Map<String, FakePlayer> playersByName = new HashMap<>();
private final Map<UUID, FakePlayer> playersByUUID = new HashMap<>(); private final Map<UUID, FakePlayer> playersByUUID = new HashMap<>();

View File

@ -1,9 +1,12 @@
package io.github.hello09x.fakeplayer.core.manager; package io.github.hello09x.fakeplayer.core.manager;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import io.github.hello09x.bedrock.command.MessageException; import io.github.hello09x.bedrock.command.MessageException;
import io.github.hello09x.bedrock.i18n.I18n; import io.github.hello09x.bedrock.i18n.I18n;
import io.github.hello09x.bedrock.util.AddressUtils; import io.github.hello09x.bedrock.util.AddressUtils;
import io.github.hello09x.fakeplayer.api.spi.Action; import io.github.hello09x.fakeplayer.api.spi.Action;
import io.github.hello09x.fakeplayer.api.spi.NMSBridge;
import io.github.hello09x.fakeplayer.core.Main; import io.github.hello09x.fakeplayer.core.Main;
import io.github.hello09x.fakeplayer.core.config.FakeplayerConfig; import io.github.hello09x.fakeplayer.core.config.FakeplayerConfig;
import io.github.hello09x.fakeplayer.core.constant.MetadataKeys; import io.github.hello09x.fakeplayer.core.constant.MetadataKeys;
@ -43,27 +46,30 @@ import static net.kyori.adventure.text.Component.textOfChildren;
import static net.kyori.adventure.text.format.NamedTextColor.GRAY; import static net.kyori.adventure.text.format.NamedTextColor.GRAY;
import static net.kyori.adventure.text.format.TextDecoration.ITALIC; import static net.kyori.adventure.text.format.TextDecoration.ITALIC;
@Singleton
public class FakeplayerManager { public class FakeplayerManager {
public final static FakeplayerManager instance = new FakeplayerManager();
private final static Logger log = Main.getInstance().getLogger(); private final static Logger log = Main.getInstance().getLogger();
private final FakeplayerConfig config = FakeplayerConfig.instance;
private final UsedIdRepository usedIdRepository = UsedIdRepository.instance;
private final NameManager nameManager = NameManager.instance;
private final FakeplayerList playerList = FakeplayerList.instance;
private final UserConfigManager configManager = UserConfigManager.instance;
private final I18n i18n = Main.getI18n(); private final I18n i18n = Main.getI18n();
private final Invsee invsee;
private final Invsee invsee = Invsee.getInstance(); private final UsedIdRepository usedIdRepository;
private final NameManager nameManager;
private final FakeplayerList playerList;
private final UserConfigManager configManager;
private final NMSBridge nms;
private final FakeplayerConfig config;
@Inject
public FakeplayerManager(Invsee invsee, UsedIdRepository usedIdRepository, NameManager nameManager, FakeplayerList playerList, UserConfigManager configManager, NMSBridge nms, FakeplayerConfig config) {
this.invsee = invsee;
this.usedIdRepository = usedIdRepository;
this.nameManager = nameManager;
this.playerList = playerList;
this.configManager = configManager;
this.nms = nms;
this.config = config;
private FakeplayerManager() {
var timer = Executors.newSingleThreadScheduledExecutor(); var timer = Executors.newSingleThreadScheduledExecutor();
timer.scheduleWithFixedDelay(() -> { timer.scheduleWithFixedDelay(() -> {
if (Bukkit.getServer().getTPS()[1] < config.getKaleTps()) { if (Bukkit.getServer().getTPS()[1] < config.getKaleTps()) {
@ -273,7 +279,7 @@ public class FakeplayerManager {
} }
this.nameManager.unregister(fakeplayer.getSequenceName()); this.nameManager.unregister(fakeplayer.getSequenceName());
if (config.isDropInventoryOnQuiting()) { if (config.isDropInventoryOnQuiting()) {
Main.getBridge().createAction( this.nms.createAction(
fakeplayer.getPlayer(), fakeplayer.getPlayer(),
Action.ActionType.DROP_INVENTORY, Action.ActionType.DROP_INVENTORY,
Action.ActionSetting.once() Action.ActionSetting.once()

View File

@ -1,5 +1,7 @@
package io.github.hello09x.fakeplayer.core.manager; package io.github.hello09x.fakeplayer.core.manager;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import io.github.hello09x.fakeplayer.core.repository.UserConfigRepository; import io.github.hello09x.fakeplayer.core.repository.UserConfigRepository;
import io.github.hello09x.fakeplayer.core.repository.model.Config; import io.github.hello09x.fakeplayer.core.repository.model.Config;
import lombok.AccessLevel; import lombok.AccessLevel;
@ -12,12 +14,15 @@ import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@NoArgsConstructor(access = AccessLevel.PRIVATE) @Singleton
public class UserConfigManager { public class UserConfigManager {
public final static UserConfigManager instance = new UserConfigManager(); private final UserConfigRepository repository;
private final UserConfigRepository repository = UserConfigRepository.instance; @Inject
public UserConfigManager(UserConfigRepository repository) {
this.repository = repository;
}
/** /**
* 获取配置值 * 获取配置值

View File

@ -1,6 +1,8 @@
package io.github.hello09x.fakeplayer.core.manager; package io.github.hello09x.fakeplayer.core.manager;
import com.google.common.io.ByteStreams; import com.google.common.io.ByteStreams;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import io.github.hello09x.fakeplayer.core.Main; import io.github.hello09x.fakeplayer.core.Main;
import io.github.hello09x.fakeplayer.core.config.FakeplayerConfig; import io.github.hello09x.fakeplayer.core.config.FakeplayerConfig;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
@ -13,9 +15,9 @@ import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Logger; import java.util.logging.Logger;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@Singleton
public class WildFakeplayerManager implements PluginMessageListener { public class WildFakeplayerManager implements PluginMessageListener {
public final static WildFakeplayerManager instance = new WildFakeplayerManager();
private final static Logger log = Main.getInstance().getLogger(); private final static Logger log = Main.getInstance().getLogger();
private final static boolean IS_BUNGEECORD = Bukkit private final static boolean IS_BUNGEECORD = Bukkit
.getServer() .getServer()
@ -33,11 +35,14 @@ public class WildFakeplayerManager implements PluginMessageListener {
private final static int CLEANUP_THRESHOLD = 2; private final static int CLEANUP_THRESHOLD = 2;
private final static int CLEANUP_PERIOD = 6000; private final static int CLEANUP_PERIOD = 6000;
private final FakeplayerManager manager = FakeplayerManager.instance; private final FakeplayerManager manager;
private final FakeplayerConfig config = FakeplayerConfig.instance; private final FakeplayerConfig config;
private final Map<String, AtomicInteger> offline = new HashMap<>(); private final Map<String, AtomicInteger> offline = new HashMap<>();
public WildFakeplayerManager() { @Inject
public WildFakeplayerManager(FakeplayerManager manager, FakeplayerConfig config) {
this.manager = manager;
this.config = config;
Bukkit.getScheduler().runTaskTimer(Main.getInstance(), this::cleanup, 0, CLEANUP_PERIOD); Bukkit.getScheduler().runTaskTimer(Main.getInstance(), this::cleanup, 0, CLEANUP_PERIOD);
} }

View File

@ -1,5 +1,7 @@
package io.github.hello09x.fakeplayer.core.manager.action; package io.github.hello09x.fakeplayer.core.manager.action;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import io.github.hello09x.fakeplayer.api.spi.Action; import io.github.hello09x.fakeplayer.api.spi.Action;
import io.github.hello09x.fakeplayer.api.spi.ActionTicker; import io.github.hello09x.fakeplayer.api.spi.ActionTicker;
import io.github.hello09x.fakeplayer.api.spi.NMSBridge; import io.github.hello09x.fakeplayer.api.spi.NMSBridge;
@ -12,15 +14,16 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.UUID;
@Singleton
public class ActionManager { public class ActionManager {
public final static ActionManager instance = new ActionManager();
private final Map<UUID, Map<Action.ActionType, ActionTicker>> managers = new HashMap<>(); private final Map<UUID, Map<Action.ActionType, ActionTicker>> managers = new HashMap<>();
private final NMSBridge bridge = Main.getBridge(); private final NMSBridge bridge;
public ActionManager() { @Inject
public ActionManager(NMSBridge bridge) {
this.bridge = bridge;
Bukkit.getScheduler().runTaskTimer(Main.getInstance(), this::tick, 0, 1); Bukkit.getScheduler().runTaskTimer(Main.getInstance(), this::tick, 0, 1);
} }

View File

@ -1,38 +1,11 @@
package io.github.hello09x.fakeplayer.core.manager.invsee; package io.github.hello09x.fakeplayer.core.manager.invsee;
import com.google.common.base.Throwables;
import io.github.hello09x.fakeplayer.core.Main;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
public interface Invsee { public interface Invsee {
static @NotNull Invsee getInstance() {
return ImplHolder.instance;
}
void openInventory(@NotNull Player visitor, @NotNull Player visited); void openInventory(@NotNull Player visitor, @NotNull Player visited);
class ImplHolder {
static Invsee instance;
static {
if (Bukkit.getPluginManager().getPlugin("OpenInv") != null) {
try {
instance = new OpenInvInvseeImpl();
} catch (Throwable e) {
Main.getInstance().getLogger().warning(Throwables.getStackTraceAsString(e));
}
} else {
instance = new DefaultInvseeImpl();
}
}
}
} }

View File

@ -1,5 +1,7 @@
package io.github.hello09x.fakeplayer.core.manager.naming; package io.github.hello09x.fakeplayer.core.manager.naming;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import io.github.hello09x.bedrock.i18n.I18n; import io.github.hello09x.bedrock.i18n.I18n;
import io.github.hello09x.fakeplayer.core.Main; import io.github.hello09x.fakeplayer.core.Main;
import io.github.hello09x.fakeplayer.core.config.FakeplayerConfig; import io.github.hello09x.fakeplayer.core.config.FakeplayerConfig;
@ -25,22 +27,26 @@ import static net.kyori.adventure.text.Component.text;
import static net.kyori.adventure.text.format.NamedTextColor.RED; import static net.kyori.adventure.text.format.NamedTextColor.RED;
import static net.kyori.adventure.text.format.NamedTextColor.WHITE; import static net.kyori.adventure.text.format.NamedTextColor.WHITE;
@Singleton
public class NameManager { public class NameManager {
public final static NameManager instance = new NameManager();
private final static Logger log = Main.getInstance().getLogger(); private final static Logger log = Main.getInstance().getLogger();
private final static int MAX_LENGTH = 16; // mojang required private final static int MAX_LENGTH = 16; // mojang required
private final static int MIN_LENGTH = 3; // mojang required private final static int MIN_LENGTH = 3; // mojang required
private final static String FALLBACK_NAME = "_fp_"; private final static String FALLBACK_NAME = "_fp_";
private final UsedIdRepository usedIdRepository = UsedIdRepository.instance; private final UsedIdRepository usedIdRepository;
private final FakeplayerConfig config = FakeplayerConfig.instance; private final FakeplayerConfig config;
private final Map<String, NameSource> nameSources = new HashMap<>(); private final Map<String, NameSource> nameSources = new HashMap<>();
private final I18n i18n = Main.getI18n(); private final I18n i18n = Main.getI18n();
private final String serverId; private final String serverId;
public NameManager() { @Inject
public NameManager(UsedIdRepository usedIdRepository, FakeplayerConfig config) {
this.usedIdRepository = usedIdRepository;
this.config = config;
var file = new File(Main.getInstance().getDataFolder(), "serverid"); var file = new File(Main.getInstance().getDataFolder(), "serverid");
serverId = Optional.ofNullable(loadServerId(file)).orElseGet(() -> { serverId = Optional.ofNullable(loadServerId(file)).orElseGet(() -> {
var uuid = UUID.randomUUID().toString(); var uuid = UUID.randomUUID().toString();

View File

@ -1,6 +1,8 @@
package io.github.hello09x.fakeplayer.core.repository; package io.github.hello09x.fakeplayer.core.repository;
import com.google.common.base.Throwables; import com.google.common.base.Throwables;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import io.github.hello09x.fakeplayer.core.Main; import io.github.hello09x.fakeplayer.core.Main;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -14,14 +16,15 @@ import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.logging.Logger; import java.util.logging.Logger;
@Singleton
public class UsedIdRepository { public class UsedIdRepository {
public final static UsedIdRepository instance = new UsedIdRepository(); public final static UsedIdRepository instance = new UsedIdRepository();
private final static Logger log = Main.getInstance().getLogger(); private final static Logger log = Main.getInstance().getLogger();
private final Set<UUID> UUIDS = new HashSet<>(); private final Set<UUID> UUIDS = new HashSet<>();
@Inject
public UsedIdRepository() { public UsedIdRepository() {
this.load(); this.load();
Main.getInstance().registerOnDisable(this::saveAll); Main.getInstance().registerOnDisable(this::saveAll);

View File

@ -1,10 +1,10 @@
package io.github.hello09x.fakeplayer.core.repository; package io.github.hello09x.fakeplayer.core.repository;
import com.google.inject.Singleton;
import io.github.hello09x.bedrock.database.Repository; import io.github.hello09x.bedrock.database.Repository;
import io.github.hello09x.fakeplayer.core.Main; import io.github.hello09x.fakeplayer.core.Main;
import io.github.hello09x.fakeplayer.core.repository.model.Config; import io.github.hello09x.fakeplayer.core.repository.model.Config;
import io.github.hello09x.fakeplayer.core.repository.model.UserConfig; import io.github.hello09x.fakeplayer.core.repository.model.UserConfig;
import org.bukkit.plugin.Plugin;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@ -14,28 +14,27 @@ import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.UUID; import java.util.UUID;
@Singleton
public class UserConfigRepository extends Repository<UserConfig> { public class UserConfigRepository extends Repository<UserConfig> {
public final static UserConfigRepository instance = new UserConfigRepository(Main.getInstance()); public UserConfigRepository() {
super(Main.getInstance());
public UserConfigRepository(Plugin plugin) {
super(plugin);
} }
public @Nullable String select(@NotNull UUID playerId, @NotNull Config<?> config) { public @Nullable String select(@NotNull UUID playerId, @NotNull Config<?> config) {
var sql = """ var sql = """
select * from user_config select * from user_config
where player_id = ? where player_id = ?
and `key` = ? and `key` = ?
"""; """;
return execute(connection -> { return execute(connection -> {
try (PreparedStatement stm = connection.prepareStatement(sql)) { try (PreparedStatement stm = connection.prepareStatement(sql)) {
stm.setString(1, playerId.toString()); stm.setString(1, playerId.toString());
stm.setString(2, config.key()); stm.setString(2, config.key());
return Optional.ofNullable(mapOne(stm.executeQuery())) return Optional.ofNullable(mapOne(stm.executeQuery()))
.map(UserConfig::value) .map(UserConfig::value)
.orElse(null); .orElse(null);
} }
}); });
} }
@ -85,18 +84,18 @@ public class UserConfigRepository extends Repository<UserConfig> {
execute(connection -> { execute(connection -> {
try (Statement stm = connection.createStatement()) { try (Statement stm = connection.createStatement()) {
stm.execute(""" stm.execute("""
create table if not exists user_config create table if not exists user_config
( (
id integer not null primary key autoincrement, id integer not null primary key autoincrement,
player_id text(36) not null, player_id text(36) not null,
`key` text not null, `key` text not null,
`value` text not null `value` text not null
); );
"""); """);
stm.execute(""" stm.execute("""
create unique index if not exists table_name_player_id_key_uindex create unique index if not exists table_name_player_id_key_uindex
on user_config (player_id, `key`); on user_config (player_id, `key`);
"""); """);
} }
}); });
} }

View File

@ -1,5 +1,6 @@
package io.github.hello09x.fakeplayer.core.repository.model; package io.github.hello09x.fakeplayer.core.repository.model;
import io.github.hello09x.fakeplayer.core.Main;
import io.github.hello09x.fakeplayer.core.command.Permission; import io.github.hello09x.fakeplayer.core.command.Permission;
import io.github.hello09x.fakeplayer.core.manager.FakeplayerManager; import io.github.hello09x.fakeplayer.core.manager.FakeplayerManager;
import net.kyori.adventure.translation.Translatable; import net.kyori.adventure.translation.Translatable;
@ -132,7 +133,7 @@ public record Config<T>(
List.of("true", "false"), List.of("true", "false"),
Permission.replenish, Permission.replenish,
Boolean::valueOf, Boolean::valueOf,
new Accessor<>(FakeplayerManager.instance::isReplenish, FakeplayerManager.instance::setReplenish) new Accessor<>(Main.getInjector().getInstance(FakeplayerManager.class)::isReplenish, Main.getInjector().getInstance(FakeplayerManager.class)::setReplenish)
); );
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")

View File

@ -22,7 +22,7 @@ import java.util.logging.Logger;
public class FakeServerGamePacketListenerImpl extends ServerGamePacketListenerImpl implements NMSServerGamePacketListener { public class FakeServerGamePacketListenerImpl extends ServerGamePacketListenerImpl implements NMSServerGamePacketListener {
private final static FakeplayerManager manager = FakeplayerManager.instance; private final FakeplayerManager manager = Main.getInjector().getInstance(FakeplayerManager.class);
private final static Logger log = Main.getInstance().getLogger(); private final static Logger log = Main.getInstance().getLogger();
public FakeServerGamePacketListenerImpl( public FakeServerGamePacketListenerImpl(

View File

@ -3,6 +3,7 @@ package io.github.hello09x.fakeplayer.v1_21_R1.spi;
import io.github.hello09x.fakeplayer.api.spi.Action; import io.github.hello09x.fakeplayer.api.spi.Action;
import io.github.hello09x.fakeplayer.api.spi.ActionTicker; import io.github.hello09x.fakeplayer.api.spi.ActionTicker;
import io.github.hello09x.fakeplayer.api.spi.NMSBridge;
import io.github.hello09x.fakeplayer.core.entity.action.BaseActionTicker; import io.github.hello09x.fakeplayer.core.entity.action.BaseActionTicker;
import io.github.hello09x.fakeplayer.v1_21_R1.action.AttackAction; import io.github.hello09x.fakeplayer.v1_21_R1.action.AttackAction;
import io.github.hello09x.fakeplayer.v1_21_R1.action.MineAction; import io.github.hello09x.fakeplayer.v1_21_R1.action.MineAction;
@ -13,8 +14,8 @@ import org.jetbrains.annotations.NotNull;
public class ActionTickerImpl extends BaseActionTicker implements ActionTicker { public class ActionTickerImpl extends BaseActionTicker implements ActionTicker {
public ActionTickerImpl(@NotNull Player player, @NotNull Action.ActionType action, @NotNull Action.ActionSetting setting) { public ActionTickerImpl(@NotNull NMSBridge nms, @NotNull Player player, @NotNull Action.ActionType action, @NotNull Action.ActionSetting setting) {
super(player, action, setting); super(nms, player, action, setting);
if (this.action == null) { if (this.action == null) {
this.action = switch (action) { this.action = switch (action) {
case ATTACK -> new AttackAction(((CraftPlayer) player).getHandle()); case ATTACK -> new AttackAction(((CraftPlayer) player).getHandle());

View File

@ -1,6 +1,7 @@
package io.github.hello09x.fakeplayer.v1_21_R1.spi; package io.github.hello09x.fakeplayer.v1_21_R1.spi;
import io.github.hello09x.fakeplayer.api.spi.*; import io.github.hello09x.fakeplayer.api.spi.*;
import io.github.hello09x.fakeplayer.core.Main;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Server; import org.bukkit.Server;
import org.bukkit.World; import org.bukkit.World;
@ -47,7 +48,7 @@ public class NMSBridgeImpl implements NMSBridge {
@Override @Override
public @NotNull ActionTicker createAction(@NotNull Player player, @NotNull Action.ActionType action, @NotNull Action.ActionSetting setting) { public @NotNull ActionTicker createAction(@NotNull Player player, @NotNull Action.ActionType action, @NotNull Action.ActionSetting setting) {
return new ActionTickerImpl(player, action, setting); return new ActionTickerImpl(Main.getInjector().getInstance(NMSBridge.class), player, action, setting);
} }
} }

View File

@ -107,6 +107,12 @@
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
<version>7.0.0</version>
</dependency>
</dependencies> </dependencies>
</dependencyManagement> </dependencyManagement>