diff --git a/fakeplayer-api/src/main/java/io/github/hello09x/fakeplayer/api/spi/ActionTicker.java b/fakeplayer-api/src/main/java/io/github/hello09x/fakeplayer/api/spi/ActionTicker.java index 9f265df..935832a 100644 --- a/fakeplayer-api/src/main/java/io/github/hello09x/fakeplayer/api/spi/ActionTicker.java +++ b/fakeplayer-api/src/main/java/io/github/hello09x/fakeplayer/api/spi/ActionTicker.java @@ -1,7 +1,12 @@ package io.github.hello09x.fakeplayer.api.spi; +import org.jetbrains.annotations.NotNull; + public interface ActionTicker { + @NotNull + ActionSetting getSetting(); + /** * 时刻计算 * diff --git a/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/Main.java b/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/Main.java index a610454..e60f4c5 100644 --- a/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/Main.java +++ b/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/Main.java @@ -99,7 +99,7 @@ public final class Main extends JavaPlugin { } } catch (Throwable e) { - getLogger().warning("检测新版本发生异常: " + e.getMessage()); + getLogger().warning("Error on checking for updates: " + e.getMessage()); } }); } diff --git a/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/command/CommandRegistry.java b/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/command/CommandRegistry.java index f874ab1..ba1f1ae 100644 --- a/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/command/CommandRegistry.java +++ b/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/command/CommandRegistry.java @@ -10,7 +10,7 @@ import io.github.hello09x.fakeplayer.api.spi.ActionType; import io.github.hello09x.fakeplayer.core.command.impl.*; import io.github.hello09x.fakeplayer.core.config.FakeplayerConfig; import io.github.hello09x.fakeplayer.core.constant.Direction; -import io.github.hello09x.fakeplayer.core.repository.model.Config; +import io.github.hello09x.fakeplayer.core.repository.model.FeatureKey; import org.bukkit.entity.Entity; import org.bukkit.entity.LivingEntity; @@ -172,8 +172,8 @@ public class CommandRegistry { .withShortDescription("fakeplayer.command.set.description") .withPermission(Permission.set) .withArguments( - config("config", Config::hasAccessor), - configValue("config", "value") + configKey("feature", FeatureKey::hasModifier), + configValue("feature", "option") ) .withOptionalArguments(fakeplayer("name")) .executes(setCommand::set), @@ -183,13 +183,13 @@ public class CommandRegistry { .withSubcommands( command("set") .withArguments( - config("config"), - configValue("config", "value")) + configKey("feature"), + configValue("feature", "option")) .executesPlayer(configCommand::setConfig), command("list") - .executes(configCommand::listConfig) + .executesPlayer(configCommand::listConfig) ) - .executes(configCommand::listConfig), + .executesPlayer(configCommand::listConfig), command("expme") .withPermission(Permission.expme) diff --git a/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/command/CommandSupports.java b/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/command/CommandSupports.java index 6c25f12..214d4c9 100644 --- a/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/command/CommandSupports.java +++ b/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/command/CommandSupports.java @@ -11,13 +11,16 @@ import io.github.hello09x.fakeplayer.core.Main; import io.github.hello09x.fakeplayer.core.command.impl.ActionCommand; import io.github.hello09x.fakeplayer.core.config.FakeplayerConfig; import io.github.hello09x.fakeplayer.core.manager.FakeplayerManager; -import io.github.hello09x.fakeplayer.core.repository.model.Config; +import io.github.hello09x.fakeplayer.core.repository.model.FeatureKey; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.*; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Locale; import java.util.concurrent.CompletableFuture; import java.util.function.Predicate; import java.util.stream.Stream; @@ -123,42 +126,56 @@ public abstract class CommandSupports { })); } - public static @NotNull Argument> config(@NotNull String nodeName) { - return config(nodeName, null); + public static @NotNull Argument configKey(@NotNull String nodeName) { + return configKey(nodeName, ignored -> true); } - public static @NotNull Argument> config(@NotNull String nodeName, @Nullable Predicate> predicate) { + public static @NotNull Argument configKey(@NotNull String nodeName, @NotNull Predicate predicate) { return new CustomArgument<>(new StringArgument(nodeName), info -> { var arg = info.currentInput(); - Config config; + FeatureKey key; try { - config = io.github.hello09x.fakeplayer.core.repository.model.Config.valueOf(arg); + key = FeatureKey.valueOf(arg); } catch (Exception e) { - throw CustomArgument.CustomArgumentException.fromAdventureComponent(translatable("fakeplayer.command.config.set.error.invalid-option")); + throw CustomArgument.CustomArgumentException.fromAdventureComponent(translatable("fakeplayer.command.config.set.error.invalid-key")); } - if (predicate != null && !predicate.test(config)) { - throw CustomArgument.CustomArgumentException.fromAdventureComponent(translatable("fakeplayer.command.config.set.error.invalid-option")); + + if (!predicate.test(key)) { + throw CustomArgument.CustomArgumentException.fromAdventureComponent(translatable("fakeplayer.command.config.set.error.invalid-key")); } - return config; - }).replaceSuggestions(ArgumentSuggestions.strings(Arrays.stream(Config.values()).filter(Optional.ofNullable(predicate).orElse(ignored -> true)).map(io.github.hello09x.fakeplayer.core.repository.model.Config::key).toList())); + + if (!key.testPermissions(info.sender())) { + throw CustomArgument.CustomArgumentException.fromAdventureComponent(translatable("fakeplayer.command.config.set.error.no-permission")); + } + return key; + }).replaceSuggestions(ArgumentSuggestions.strings(Arrays.stream(FeatureKey.values()).filter(predicate).map(Enum::name).toArray(String[]::new))); } - public static @NotNull Argument configValue(@NotNull String configNodeName, @NotNull String nodeName) { - return new CustomArgument<>(new StringArgument(nodeName), info -> { - @SuppressWarnings("unchecked") - var config = Objects.requireNonNull((Config) info.previousArgs().get(configNodeName)); + + public static @NotNull Argument configValue(@NotNull String configKeyNodeName, @NotNull String nodeName) { + return new CustomArgument(new StringArgument(nodeName), info -> { + var key = (FeatureKey) info.previousArgs().get(configKeyNodeName); + if (key == null) { + throw CustomArgument.CustomArgumentException.fromAdventureComponent(translatable("fakeplayer.command.config.set.error.invalid-key")); + } var arg = info.currentInput(); - if (!config.options().contains(arg)) { + if (!key.getOptions().contains(arg)) { throw CustomArgument.CustomArgumentException.fromAdventureComponent(translatable("fakeplayer.command.config.set.error.invalid-value")); } - return config.parser().apply(arg); - }).replaceSuggestions(ArgumentSuggestions.stringsAsync(info -> CompletableFuture.supplyAsync(() -> {var config = Objects.requireNonNull((io.github.hello09x.fakeplayer.core.repository.model.Config) info.previousArgs().get(configNodeName)); - var arg = info.currentArg().toLowerCase(); - var options = config.options().stream(); - if (!arg.isEmpty()) { - options = options.filter(o -> o.toLowerCase().contains(arg)); + + return arg; + }).replaceSuggestions(ArgumentSuggestions.stringCollectionAsync(info -> CompletableFuture.supplyAsync(() -> { + var key = (FeatureKey) info.previousArgs().get(configKeyNodeName); + if (key == null) { + return Collections.emptyList(); } - return options.toArray(String[]::new); + + var arg = info.currentArg().toLowerCase(Locale.ENGLISH); + if (arg.isEmpty()) { + return key.getOptions(); + } + + return key.getOptions().stream().filter(option -> option.contains(arg)).toList(); }))); } diff --git a/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/command/impl/ConfigCommand.java b/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/command/impl/ConfigCommand.java index 05acc38..0b19dd3 100644 --- a/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/command/impl/ConfigCommand.java +++ b/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/command/impl/ConfigCommand.java @@ -8,17 +8,14 @@ import dev.jorel.commandapi.executors.CommandArguments; import io.github.hello09x.devtools.core.translation.TranslatorUtils; import io.github.hello09x.devtools.core.utils.ComponentUtils; import io.github.hello09x.fakeplayer.core.Main; -import io.github.hello09x.fakeplayer.core.manager.UserConfigManager; -import io.github.hello09x.fakeplayer.core.repository.model.Config; +import io.github.hello09x.fakeplayer.core.manager.feature.FakeplayerFeatureManager; +import io.github.hello09x.fakeplayer.core.repository.model.FeatureKey; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.Style; import org.bukkit.Bukkit; -import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; -import java.util.ArrayList; -import java.util.Arrays; import java.util.Objects; import java.util.concurrent.CompletableFuture; @@ -31,57 +28,52 @@ import static net.kyori.adventure.text.format.TextDecoration.UNDERLINED; @Singleton public class ConfigCommand extends AbstractCommand { - private final UserConfigManager configManager; + private final FakeplayerFeatureManager featureManager; @Inject - public ConfigCommand(UserConfigManager configManager) { - this.configManager = configManager; + public ConfigCommand(FakeplayerFeatureManager featureManager) { + this.featureManager = featureManager; } /** * 设置配置 */ public void setConfig(@NotNull Player sender, @NotNull CommandArguments args) throws WrapperCommandSyntaxException { - @SuppressWarnings("unchecked") - var config = (Config) Objects.requireNonNull(args.get("config")); - - if (!config.hasPermission(sender)) { + var key = (FeatureKey) Objects.requireNonNull(args.get("feature")); + if (!key.testPermissions(sender)) { throw CommandAPI.failWithString(ComponentUtils.toString( translatable("fakeplayer.command.config.set.error.no-permission"), TranslatorUtils.getLocale(sender) )); } - var value = Objects.requireNonNull(args.get("value")); - configManager.setConfig(sender, config, value); + var option = (String) Objects.requireNonNull(args.get("option")); + featureManager.setFeature(sender, key, option); sender.sendMessage(translatable( "fakeplayer.command.config.set.success", - translatable(config.translationKey(), GOLD), - text(value.toString(), WHITE) + translatable(key.translationKey(), GOLD), + text(option, WHITE) ).color(GRAY)); } /** * 获取所有配置 */ - public void listConfig(@NotNull CommandSender sender, @NotNull CommandArguments args) { + public void listConfig(@NotNull Player sender, @NotNull CommandArguments args) { CompletableFuture.runAsync(() -> { - var components = Arrays.stream(Config.values()).map(config -> { - var options = new ArrayList<>(config.options()); - var value = String.valueOf(configManager.getConfig(sender, config)); - return textOfChildren( - translatable(config, GOLD), - text(": ", GRAY), - join(separator(space()), options.stream().map(option -> { - var style = option.equals(value) ? Style.style(GREEN, UNDERLINED) : Style.style(GRAY); - return text("[" + option + "]").style(style).clickEvent( - runCommand("/fp config set " + config.key() + " " + option) - ); - }).toList()) - ); - }).toList(); - - var message = Component.join(separator(newline()), components); + var lines = featureManager.getFeatures(sender).values().stream().map(feature -> textOfChildren( + translatable(feature.key(), GOLD), + text(": ", GRAY), + join(separator(space()), feature.key().getOptions().stream().map(option -> { + var style = option.equals(feature.value()) + ? Style.style(GREEN, UNDERLINED) + : Style.style(GRAY); + return text("[" + option + "]").style(style).clickEvent( + runCommand("/fp config set " + feature.key() + " " + option) + ); + }).toList()) + )).toList(); + var message = Component.join(separator(newline()), lines); Bukkit.getScheduler().runTask(Main.getInstance(), () -> sender.sendMessage(message)); }); } diff --git a/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/command/impl/ReloadCommand.java b/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/command/impl/ReloadCommand.java index 5dc7dbe..c973ee0 100644 --- a/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/command/impl/ReloadCommand.java +++ b/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/command/impl/ReloadCommand.java @@ -8,9 +8,8 @@ import io.github.hello09x.fakeplayer.core.config.FakeplayerConfig; import org.bukkit.command.CommandSender; import org.jetbrains.annotations.NotNull; -import static net.kyori.adventure.text.Component.text; import static net.kyori.adventure.text.Component.translatable; -import static net.kyori.adventure.text.format.NamedTextColor.*; +import static net.kyori.adventure.text.format.NamedTextColor.GRAY; @Singleton public class ReloadCommand extends AbstractCommand { @@ -27,15 +26,8 @@ public class ReloadCommand extends AbstractCommand { public void reload(@NotNull CommandSender sender, @NotNull CommandArguments args) { config.reload(); - if (!config.isFileExists()) { - sender.sendMessage(translatable( - "fakeplayer.command.reload.config-file-not-found", - text(FakeplayerConfig.CONFIG_FILE_NAME, WHITE), - text(FakeplayerConfig.CONFIG_TMPL_FILE_NAME, WHITE) - ).color(GOLD)); - } sender.sendMessage(translatable("fakeplayer.command.generic.success", GRAY)); - if (config.isFileConfigurationOutOfDate()) { + if (config.isConfigFileOutOfDate()) { sender.sendMessage(translatable("fakeplayer.configuration.out-of-date", GRAY)); } } diff --git a/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/command/impl/SetCommand.java b/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/command/impl/SetCommand.java index b7c02fb..7623a7e 100644 --- a/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/command/impl/SetCommand.java +++ b/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/command/impl/SetCommand.java @@ -3,7 +3,7 @@ package io.github.hello09x.fakeplayer.core.command.impl; import com.google.inject.Singleton; import dev.jorel.commandapi.exceptions.WrapperCommandSyntaxException; import dev.jorel.commandapi.executors.CommandArguments; -import io.github.hello09x.fakeplayer.core.repository.model.Config; +import io.github.hello09x.fakeplayer.core.repository.model.FeatureKey; import org.bukkit.command.CommandSender; import org.jetbrains.annotations.NotNull; @@ -18,26 +18,24 @@ public class SetCommand extends AbstractCommand { public void set(@NotNull CommandSender sender, @NotNull CommandArguments args) throws WrapperCommandSyntaxException { var target = super.getFakeplayer(sender, args); + var key = (FeatureKey) Objects.requireNonNull(args.get("feature")); + var value = (String) Objects.requireNonNull(args.get("option")); - @SuppressWarnings("unchecked") - var config = Objects.requireNonNull((Config) args.get("config")); - if (!config.hasPermission(sender)) { - sender.sendMessage(translatable("fakeplayer.command.config.set.error.no-permission", RED)); + var modifier = key.getModifier(); + if (modifier == null) { + sender.sendMessage(translatable("fakeplayer.command.config.set.error.invalid-key", RED)); return; } - if (!config.hasAccessor()) { - sender.sendMessage(translatable("fakeplayer.command.config.set.error.invalid-option", RED)); - return; - } - var value = Objects.requireNonNull(args.get("value")); - config.accessor().setter().accept(target, value); + modifier.accept(target, value); sender.sendMessage(translatable( "fakeplayer.command.set.success", text(target.getName(), WHITE), - translatable(config, GOLD), - text(value.toString(), WHITE) + translatable(key, GOLD), + text(value, WHITE) ).color(GRAY)); + + } } diff --git a/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/command/impl/StatusCommand.java b/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/command/impl/StatusCommand.java index aded74f..11f506d 100644 --- a/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/command/impl/StatusCommand.java +++ b/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/command/impl/StatusCommand.java @@ -5,7 +5,7 @@ import dev.jorel.commandapi.exceptions.WrapperCommandSyntaxException; import dev.jorel.commandapi.executors.CommandArguments; import io.github.hello09x.devtools.core.utils.ExperienceUtils; import io.github.hello09x.fakeplayer.core.command.Permission; -import io.github.hello09x.fakeplayer.core.repository.model.Config; +import io.github.hello09x.fakeplayer.core.repository.model.FeatureKey; import io.github.hello09x.fakeplayer.core.util.Mth; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.JoinConfiguration; @@ -19,11 +19,10 @@ import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; -import java.util.Arrays; import java.util.Optional; -import java.util.stream.Collectors; import static net.kyori.adventure.text.Component.*; +import static net.kyori.adventure.text.JoinConfiguration.separator; import static net.kyori.adventure.text.event.ClickEvent.runCommand; import static net.kyori.adventure.text.format.NamedTextColor.*; import static net.kyori.adventure.text.format.TextDecoration.UNDERLINED; @@ -68,7 +67,7 @@ public class StatusCommand extends AbstractCommand { lines.add(this.getExperienceLine(fake)); } lines.add(LINE_SPLITTER); - lines.add(getConfigLine(fake)); + lines.add(getFeatureLine(fake)); sender.sendMessage(join(JoinConfiguration.newlines(), lines)); } @@ -117,23 +116,26 @@ public class StatusCommand extends AbstractCommand { ); } - private @NotNull Component getConfigLine(@NotNull Player target) { - var configs = Arrays.stream(Config.values()).filter(Config::hasAccessor).toList(); + private @NotNull Component getFeatureLine(@NotNull Player faker) { var messages = new ArrayList(); - for (var config : configs) { - var name = translatable(config.translationKey(), WHITE); - var options = config.options(); - var status = config.accessor().getter().apply(target).toString(); + for (var key : FeatureKey.values()) { + var detector = key.getDetector(); + if (detector == null) { + continue; + } + var name = translatable(key, WHITE); + var options = key.getOptions(); + var status = detector.apply(faker); messages.add(textOfChildren( name, space(), - join(JoinConfiguration.separator(space()), options.stream().map(option -> { + join(separator(space()), options.stream().map(option -> { var style = option.equals(status) ? Style.style(GREEN, UNDERLINED) : Style.style(GRAY); return text("[" + option + "]").style(style).clickEvent( - runCommand("/fp set %s %s %s".formatted(config.key(), option, target.getName())) + runCommand("/fp set %s %s %s".formatted(key.name(), option, faker.getName())) ); - }).collect(Collectors.toList())) + }).toList()) )); } return join(JoinConfiguration.newlines(), messages); diff --git a/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/config/FakeplayerConfig.java b/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/config/FakeplayerConfig.java index 6fa9abf..12be8a2 100644 --- a/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/config/FakeplayerConfig.java +++ b/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/config/FakeplayerConfig.java @@ -7,6 +7,7 @@ import com.google.inject.Singleton; import io.github.hello09x.devtools.core.config.ConfigUtils; import io.github.hello09x.devtools.core.config.PluginConfig; import io.github.hello09x.fakeplayer.core.Main; +import io.github.hello09x.fakeplayer.core.repository.model.FeatureKey; import lombok.Getter; import lombok.ToString; import org.bukkit.Bukkit; @@ -15,8 +16,11 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.time.Duration; +import java.util.Arrays; import java.util.List; +import java.util.Map; import java.util.Set; +import java.util.function.Function; import java.util.logging.Logger; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; @@ -33,6 +37,8 @@ public class FakeplayerConfig extends PluginConfig { private final static String defaultNameChars = "^[a-zA-Z0-9_]+$"; + public final static String SECTION_KEY_DEFAULT_FEATURES = "default-features"; + /** * 每位玩家最多多少个假人 */ @@ -151,6 +157,8 @@ public class FakeplayerConfig extends PluginConfig { @Beta private boolean defaultOnlineSkin; + private Map defaultFeatures; + @Inject public FakeplayerConfig() { super(Main.getInstance()); @@ -189,10 +197,12 @@ public class FakeplayerConfig extends PluginConfig { .collect(Collectors.toSet()); this.defaultOnlineSkin = file.getBoolean("default-online-skin", false); + this.defaultFeatures = Arrays.stream(FeatureKey.values()) + .collect(Collectors.toMap(Function.identity(), key -> file.getString("default-features." + key.name(), key.getDefaultOption()))); this.invseeImplement = ConfigUtils.getEnum(file, "invsee-implement", InvseeImplement.class, InvseeImplement.AUTO); this.debug = file.getBoolean("debug", false); - if (this.isFileConfigurationOutOfDate()) { + if (this.isConfigFileOutOfDate()) { Bukkit.getScheduler().runTaskLater(Main.getInstance(), () -> { if (Main.getInstance().isEnabled()) { Main.getInstance().getComponentLogger().warn(translatable("fakeplayer.configuration.out-of-date")); diff --git a/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/entity/Fakeplayer.java b/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/entity/Fakeplayer.java index ca2320d..fbd7e3a 100644 --- a/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/entity/Fakeplayer.java +++ b/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/entity/Fakeplayer.java @@ -10,7 +10,6 @@ import io.github.hello09x.fakeplayer.core.config.FakeplayerConfig; import io.github.hello09x.fakeplayer.core.config.PreventKicking; import io.github.hello09x.fakeplayer.core.constant.MetadataKeys; import io.github.hello09x.fakeplayer.core.manager.FakeplayerAutofishManager; -import io.github.hello09x.fakeplayer.core.manager.FakeplayerManager; import io.github.hello09x.fakeplayer.core.manager.FakeplayerReplenishManager; import io.github.hello09x.fakeplayer.core.manager.FakeplayerSkinManager; import io.github.hello09x.fakeplayer.core.manager.action.ActionManager; @@ -44,10 +43,10 @@ public class Fakeplayer { private final static InternalAddressGenerator ipGen = new InternalAddressGenerator(); private final static FakeplayerConfig config = Main.getInjector().getInstance(FakeplayerConfig.class); private final static NMSBridge bridge = Main.getInjector().getInstance(NMSBridge.class); - private final static FakeplayerManager manager = Main.getInjector().getInstance(FakeplayerManager.class); private final static FakeplayerSkinManager skinManager = Main.getInjector().getInstance(FakeplayerSkinManager.class); private final static FakeplayerReplenishManager replenishManager = Main.getInjector().getInstance(FakeplayerReplenishManager.class); private final static FakeplayerAutofishManager autofishManager = Main.getInjector().getInstance(FakeplayerAutofishManager.class); + private final static ActionManager actionManager = Main.getInjector().getInstance(ActionManager.class); @NotNull @@ -73,15 +72,15 @@ public class Fakeplayer { @NotNull private final FakeplayerTicker ticker; - @NotNull @Getter + @NotNull private final String name; @NotNull private final UUID uuid; - @UnknownNullability @Getter + @UnknownNullability private NMSNetwork network; /** @@ -152,7 +151,7 @@ public class Fakeplayer { this.player.setCollidable(option.collidable()); this.player.setCanPickupItems(option.pickupItems()); if (option.lookAtEntity()) { - Main.getInjector().getInstance(ActionManager.class).setAction(player, ActionType.LOOK_AT_NEAREST_ENTITY, ActionSetting.continuous()); + actionManager.setAction(player, ActionType.LOOK_AT_NEAREST_ENTITY, ActionSetting.continuous()); } if (option.skin()) { skinManager.useDefaultSkin(creator, player); diff --git a/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/entity/SpawnOption.java b/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/entity/SpawnOption.java index 2b2178d..4f59ee9 100644 --- a/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/entity/SpawnOption.java +++ b/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/entity/SpawnOption.java @@ -12,6 +12,7 @@ import org.jetbrains.annotations.NotNull; * @param replenish 自动补货 */ public record SpawnOption( + @NotNull Location spawnAt, diff --git a/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/entity/action/BaseActionTicker.java b/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/entity/action/BaseActionTicker.java index bc7cda4..6deeed4 100644 --- a/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/entity/action/BaseActionTicker.java +++ b/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/entity/action/BaseActionTicker.java @@ -2,6 +2,7 @@ package io.github.hello09x.fakeplayer.core.entity.action; import io.github.hello09x.fakeplayer.api.spi.*; import io.github.hello09x.fakeplayer.core.entity.action.impl.*; +import lombok.Getter; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.UnknownNullability; @@ -17,6 +18,7 @@ public abstract class BaseActionTicker implements ActionTicker { protected Action action; @NotNull + @Getter protected ActionSetting setting; public BaseActionTicker(NMSBridge nms, @NotNull Player player, @NotNull ActionType action, @NotNull ActionSetting setting) { diff --git a/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/manager/FakeplayerManager.java b/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/manager/FakeplayerManager.java index bb79b47..39bc7ff 100644 --- a/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/manager/FakeplayerManager.java +++ b/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/manager/FakeplayerManager.java @@ -13,8 +13,9 @@ import io.github.hello09x.fakeplayer.core.config.FakeplayerConfig; import io.github.hello09x.fakeplayer.core.constant.MetadataKeys; import io.github.hello09x.fakeplayer.core.entity.Fakeplayer; import io.github.hello09x.fakeplayer.core.entity.SpawnOption; +import io.github.hello09x.fakeplayer.core.manager.feature.FakeplayerFeatureManager; import io.github.hello09x.fakeplayer.core.manager.naming.NameManager; -import io.github.hello09x.fakeplayer.core.repository.model.Config; +import io.github.hello09x.fakeplayer.core.repository.model.FeatureKey; import io.github.hello09x.fakeplayer.core.util.AddressUtils; import io.github.hello09x.fakeplayer.core.util.Commands; import net.kyori.adventure.text.Component; @@ -51,16 +52,16 @@ public class FakeplayerManager { private final NameManager nameManager; private final FakeplayerList playerList; - private final UserConfigManager configManager; + private final FakeplayerFeatureManager featureManager; private final NMSBridge nms; private final FakeplayerConfig config; private final ScheduledExecutorService lagMonitor; @Inject - public FakeplayerManager(NameManager nameManager, FakeplayerList playerList, UserConfigManager configManager, NMSBridge nms, FakeplayerConfig config) { + public FakeplayerManager(NameManager nameManager, FakeplayerList playerList, FakeplayerFeatureManager featureManager, NMSBridge nms, FakeplayerConfig config) { this.nameManager = nameManager; this.playerList = playerList; - this.configManager = configManager; + this.featureManager = featureManager; this.nms = nms; this.config = config; @@ -107,16 +108,16 @@ public class FakeplayerManager { this.dispatchCommandsEarly(fp, this.config.getPreSpawnCommands()); return CompletableFuture .supplyAsync(() -> { - var configs = configManager.getConfigs(creator); + var configs = featureManager.getFeatures(creator); return new SpawnOption( spawnAt, - configs.getOrDefault(Config.invulnerable), - configs.getOrDefault(Config.collidable), - configs.getOrDefault(Config.look_at_entity), - configs.getOrDefault(Config.pickup_items), - configs.getOrDefault(Config.skin), - configs.getOrDefault(Config.replenish), - configs.getOrDefault(Config.autofish) + configs.get(FeatureKey.invulnerable).asBoolean(), + configs.get(FeatureKey.collidable).asBoolean(), + configs.get(FeatureKey.look_at_entity).asBoolean(), + configs.get(FeatureKey.pickup_items).asBoolean(), + configs.get(FeatureKey.skin).asBoolean(), + configs.get(FeatureKey.replenish).asBoolean(), + configs.get(FeatureKey.autofish).asBoolean() ); }) .thenComposeAsync(fp::spawnAsync) diff --git a/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/manager/UserConfigManager.java b/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/manager/UserConfigManager.java deleted file mode 100644 index fc3c3b2..0000000 --- a/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/manager/UserConfigManager.java +++ /dev/null @@ -1,123 +0,0 @@ -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.model.Config; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -@Singleton -public class UserConfigManager { - - private final UserConfigRepository repository; - - @Inject - public UserConfigManager(UserConfigRepository repository) { - this.repository = repository; - } - - /** - * 获取配置值 - *

- * 如果玩家曾经设置过但随后没有了权限, 则返回默认值 - *

- * - * @param player 玩家 - * @param config 配置项 - * @return 配置值 - */ - public T getConfig(@NotNull Player player, @NotNull Config config) { - if (!config.hasPermission(player)) { - return config.defaultValue(); - } - - var value = repository.select(player.getUniqueId(), config); - if (value == null) { - return config.defaultValue(); - } - return config.parser().apply(value); - } - - /** - * 获取玩家所有配置项 - *

- * 如果玩家曾经设置过但随后没有了权限, 则不会包含在其中 - *

- * - * @param sender 玩家 - * @return 玩家有权限的配置项 - */ - public @NotNull Configs getConfigs(@NotNull CommandSender sender) { - if (!(sender instanceof Player player)) { - return new Configs(Collections.emptyMap()); - } - var configs = repository.selectList(player.getUniqueId()); - var values = new HashMap, Object>(); - for (var config : configs) { - var key = Config.valueOfOpt(config.key()).orElse(null); - if (key == null || !key.hasPermission(player)) { - continue; - } - values.put(key, key.parser().apply(config.value())); - } - return new Configs(values); - } - - /** - * 获取配置值 - *
    - *
  • 如果玩家曾经设置过但随后没有了权限, 则为默认值
  • - *
  • 如果不是玩家, 则为默认值
  • - *
- * - * @param sender 玩家 - * @param config 配置项 - * @return 配置值 - */ - public T getConfig(@NotNull CommandSender sender, @NotNull Config config) { - if (sender instanceof Player p) { - return this.getConfig(p, config); - } - return config.defaultValue(); - } - - /** - * 设置配置值 - * - * @param player 玩家 - * @param config 配置 - * @param value 配置值 - */ - public boolean setConfig(@NotNull Player player, @NotNull Config config, @NotNull T value) { - if (!config.hasPermission(player)) { - return false; - } - repository.saveOrUpdate(player.getUniqueId(), config, value); - return true; - } - - public static class Configs { - - private final Map, Object> values; - - private Configs(@NotNull Map, Object> values) { - this.values = values; - } - - public T getOrDefault(@NotNull Config key) { - var config = values.get(key); - if (config == null) { - return key.defaultValue(); - } - return key.type().cast(config); - } - - } - -} diff --git a/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/manager/action/ActionManager.java b/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/manager/action/ActionManager.java index 298731d..564e899 100644 --- a/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/manager/action/ActionManager.java +++ b/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/manager/action/ActionManager.java @@ -14,6 +14,7 @@ import org.jetbrains.annotations.NotNull; import java.util.HashMap; import java.util.Map; +import java.util.Optional; import java.util.UUID; import java.util.logging.Logger; @@ -33,6 +34,16 @@ public class ActionManager { Bukkit.getScheduler().runTaskTimer(Main.getInstance(), this::tick, 0, 1); } + public boolean hasActiveAction( + @NotNull Player player, + @NotNull ActionType action + ) { + return Optional.ofNullable(this.managers.get(player.getUniqueId())) + .map(manager -> manager.get(action)) + .filter(ac -> ac.getSetting().remains > 0) + .isPresent(); + } + public void setAction( @NotNull Player player, @NotNull ActionType action, diff --git a/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/manager/feature/FakeplayerFeatureManager.java b/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/manager/feature/FakeplayerFeatureManager.java new file mode 100644 index 0000000..c47cff1 --- /dev/null +++ b/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/manager/feature/FakeplayerFeatureManager.java @@ -0,0 +1,79 @@ +package io.github.hello09x.fakeplayer.core.manager.feature; + +import com.google.inject.Inject; +import com.google.inject.Singleton; +import io.github.hello09x.fakeplayer.core.config.FakeplayerConfig; +import io.github.hello09x.fakeplayer.core.repository.UserConfigRepository; +import io.github.hello09x.fakeplayer.core.repository.model.FeatureKey; +import io.github.hello09x.fakeplayer.core.repository.model.UserConfig; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Optional; +import java.util.function.Function; +import java.util.stream.Collectors; + +@Singleton +public class FakeplayerFeatureManager { + + private final UserConfigRepository repository; + private final FakeplayerConfig config; + + @Inject + public FakeplayerFeatureManager(UserConfigRepository repository, FakeplayerConfig config) { + this.repository = repository; + this.config = config; + } + + private @NotNull String getDefaultOption(@NotNull FeatureKey key) { + return Optional.ofNullable(config.getDefaultFeatures().get(key)).filter(option -> key.getOptions().contains(option)).orElse(key.getDefaultOption()); + } + + public @NotNull Feature getFeature(@NotNull Player player, @NotNull FeatureKey key) { + if (!key.testPermissions(player)) { + return new Feature(key, this.getDefaultOption(key)); + } + + String value = Optional.ofNullable(repository.selectByPlayerIdAndKey(player.getUniqueId(), key)) + .map(UserConfig::value) + .orElseGet(() -> this.getDefaultOption(key)); + + return new Feature(key, value); + } + + public @NotNull Map getFeatures(@NotNull CommandSender sender) { + Map userConfigs; + if (sender instanceof Player player) { + userConfigs = repository.selectByPlayerId(player.getUniqueId()).stream().collect(Collectors.toMap(UserConfig::key, Function.identity())); + } else { + userConfigs = Collections.emptyMap(); + } + + var configs = new LinkedHashMap(FeatureKey.values().length, 1.0F); + for (var key : FeatureKey.values()) { + String value; + if (!key.testPermissions(sender)) { + value = this.getDefaultOption(key); + } else { + value = Optional.ofNullable(userConfigs.get(key)).map(UserConfig::value).orElseGet(() -> this.getDefaultOption(key)); + } + configs.put(key, new Feature(key, value)); + } + + return configs; + } + + public void setFeature(@NotNull Player player, @NotNull FeatureKey key, @NotNull String value) { + this.repository.saveOrUpdate(new UserConfig( + null, + player.getUniqueId(), + key, + value + )); + } + +} diff --git a/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/manager/feature/Feature.java b/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/manager/feature/Feature.java new file mode 100644 index 0000000..43d47d7 --- /dev/null +++ b/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/manager/feature/Feature.java @@ -0,0 +1,28 @@ +package io.github.hello09x.fakeplayer.core.manager.feature; + +import io.github.hello09x.fakeplayer.core.repository.model.FeatureKey; +import org.jetbrains.annotations.NotNull; + +/** + * @author tanyaofei + * @since 2024/8/13 + **/ +public record Feature( + + @NotNull + FeatureKey key, + + @NotNull + String value + +) { + + public @NotNull String asString() { + return value; + } + + public boolean asBoolean() { + return Boolean.parseBoolean(value); + } + +} diff --git a/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/repository/UserConfigRepository.java b/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/repository/UserConfigRepository.java index 8c1e2a7..5f1934b 100644 --- a/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/repository/UserConfigRepository.java +++ b/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/repository/UserConfigRepository.java @@ -3,14 +3,13 @@ package io.github.hello09x.fakeplayer.core.repository; import com.google.inject.Inject; import com.google.inject.Singleton; import io.github.hello09x.devtools.database.jdbc.JdbcTemplate; -import io.github.hello09x.fakeplayer.core.repository.model.Config; +import io.github.hello09x.fakeplayer.core.repository.model.FeatureKey; import io.github.hello09x.fakeplayer.core.repository.model.UserConfig; import io.github.hello09x.fakeplayer.core.repository.model.UserConfigRowMapper; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.List; -import java.util.Optional; import java.util.UUID; @Singleton @@ -24,55 +23,31 @@ public class UserConfigRepository { this.initTables(); } - public @Nullable String select(@NotNull UUID playerId, @NotNull Config config) { - var sql = """ - select * from user_config - where player_id = ? - and `key` = ? - """; - - return Optional - .ofNullable(jdbc.queryForObject( - sql, - UserConfigRowMapper.instance, - playerId.toString(), - config.key()) - ) - .map(UserConfig::value) - .orElse(null); + public @Nullable UserConfig selectByPlayerIdAndKey(@NotNull UUID playerId, @NotNull FeatureKey featureKey) { + var sql = "select * from user_config where player_id = ? and `key` = ?"; + return jdbc.queryForObject(sql, UserConfigRowMapper.instance, playerId.toString(), featureKey.name()); } - public @NotNull List selectList(@NotNull UUID playerId) { + public int saveOrUpdate(@NotNull UserConfig config) { var sql = """ - select * from user_config - where player_id = ? - """; + insert or replace into user_config( + id, player_id, `key`, `value` + ) values ( + (select id from user_config where player_id = ? and `key` = ?), + ?, + ?, + ? + ) + """; + return jdbc.update(sql, config.playerId().toString(), config.key().name(), config.playerId(), config.key().name(), config.value()); + } + + public @NotNull List selectByPlayerId(@NotNull UUID playerId) { + var sql = "select * from user_config where player_id = ?"; return jdbc.query(sql, UserConfigRowMapper.instance, playerId.toString()); } - public int saveOrUpdate(@NotNull UUID playerId, @NotNull Config config, @NotNull T value) { - var sql = """ - insert or replace into user_config( - id, player_id, `key`, `value` - ) values ( - (select id from user_config where player_id = ? and `key` = ?), - ?, - ?, - ? - ) - """; - - return jdbc.update( - sql, - playerId.toString(), - config.key(), - playerId.toString(), - config.key(), - value.toString() - ); - } - protected void initTables() { jdbc.execute(""" create table if not exists user_config diff --git a/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/repository/model/Config.java b/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/repository/model/Config.java deleted file mode 100644 index 2c366e3..0000000 --- a/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/repository/model/Config.java +++ /dev/null @@ -1,204 +0,0 @@ -package io.github.hello09x.fakeplayer.core.repository.model; - -import io.github.hello09x.devtools.core.utils.SingletonSupplier; -import io.github.hello09x.fakeplayer.core.Main; -import io.github.hello09x.fakeplayer.core.command.Permission; -import io.github.hello09x.fakeplayer.core.manager.FakeplayerAutofishManager; -import io.github.hello09x.fakeplayer.core.manager.FakeplayerReplenishManager; -import net.kyori.adventure.translation.Translatable; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.annotations.UnknownNullability; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.function.BiConsumer; -import java.util.function.Function; - -/** - * @param key 配置项 key - * @param translationKey 翻译 key - * @param defaultValue 默认值 - * @param options 可选值 - * @param parser 转换器 - * @param accessor 访问器, 访问或者设置假人当前配置 - */ -public record Config( - - @NotNull - String key, - - @NotNull - String translationKey, - - @NotNull Class type, - - @NotNull - T defaultValue, - - @NotNull - List options, - - @Nullable - String permission, - - @NotNull - Function parser, - - @UnknownNullability - Accessor accessor - -) implements Translatable { - - private static final Map> values = new HashMap<>(); - private static final SingletonSupplier autofishManager = new SingletonSupplier<>(() -> Main.getInjector().getInstance(FakeplayerAutofishManager.class)); - private static final SingletonSupplier replenishManager = new SingletonSupplier<>(() -> Main.getInjector().getInstance(FakeplayerReplenishManager.class)); - - public static Config collidable = build( - "collidable", - "fakeplayer.config.collidable", - Boolean.class, - true, - List.of("true", "false"), - null, - Boolean::valueOf, - new Accessor<>(LivingEntity::isCollidable, LivingEntity::setCollidable) - ); - - /** - * 无敌 - */ - public static Config invulnerable = build( - "invulnerable", - "fakeplayer.config.invulnerable", - Boolean.class, - true, - List.of("true", "false"), - null, - Boolean::valueOf, - new Accessor<>(LivingEntity::isInvulnerable, LivingEntity::setInvulnerable) - ); - - /** - * 看向实体 - */ - public static Config look_at_entity = build( - "look_at_entity", - "fakeplayer.config.look_at_entity", - Boolean.class, - true, - List.of("true", "false"), - null, - Boolean::valueOf, - null - ); - - /** - * 拾取物品 - */ - public static Config pickup_items = build( - "pickup_items", - "fakeplayer.config.pickup_items", - Boolean.class, - true, - List.of("true", "false"), - null, - Boolean::valueOf, - new Accessor<>(LivingEntity::getCanPickupItems, LivingEntity::setCanPickupItems) - ); - - /** - * 使用皮肤 - */ - public static Config skin = build( - "skin", - "fakeplayer.config.skin", - Boolean.class, - true, - List.of("true", "false"), - null, - Boolean::valueOf, - null - ); - - /** - * 自动补货 - */ - public static Config replenish = build( - "replenish", - "fakeplayer.config.replenish", - Boolean.class, - false, - List.of("true", "false"), - Permission.replenish, - Boolean::valueOf, - new Accessor<>(replenishManager.get()::isReplenish, replenishManager.get()::setReplenish) - ); - - public static Config autofish = build( - "autofish", - "fakeplayer.config.autofish", - Boolean.class, - false, - List.of("true", "false"), - Permission.autofish, - Boolean::valueOf, - new Accessor<>(autofishManager.get()::isAutofish, autofishManager.get()::setAutofish) - ); - - @SuppressWarnings("unchecked") - public static @NotNull Config valueOf(@NotNull String name) { - return (Config) valueOfOpt(name).orElseThrow(() -> new IllegalArgumentException("No config named: " + name)); - } - - @SuppressWarnings("unchecked") - public static @NotNull Optional> valueOfOpt(@NotNull String name) { - return Optional.ofNullable((Config) values.get(name)); - } - - public static @NotNull Config[] values() { - return values.values().toArray(Config[]::new); - } - - private static Config build( - @NotNull String name, - @NotNull String translationKey, - @NotNull Class type, - @NotNull T defaultValue, - @NotNull List options, - @Nullable String permission, - @NotNull Function converter, - @Nullable Accessor accessor - ) { - var config = new Config<>(name, translationKey, type, defaultValue, options, permission, converter, accessor); - values.put(name, config); - return config; - } - - public boolean hasPermission(@NotNull CommandSender player) { - return this.permission == null || player.hasPermission(this.permission); - } - - @Override - public @NotNull String translationKey() { - return this.translationKey; - } - - public boolean hasAccessor() { - return this.accessor != null; - } - - public record Accessor( - @NotNull Function getter, - @NotNull BiConsumer setter - ) { - - } - - -} diff --git a/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/repository/model/FeatureKey.java b/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/repository/model/FeatureKey.java new file mode 100644 index 0000000..83b9f97 --- /dev/null +++ b/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/repository/model/FeatureKey.java @@ -0,0 +1,164 @@ +package io.github.hello09x.fakeplayer.core.repository.model; + +import io.github.hello09x.fakeplayer.api.spi.ActionSetting; +import io.github.hello09x.fakeplayer.api.spi.ActionType; +import io.github.hello09x.fakeplayer.core.command.Permission; +import lombok.AllArgsConstructor; +import lombok.Getter; +import net.kyori.adventure.translation.Translatable; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; +import java.util.function.BiConsumer; +import java.util.function.Function; + +/** + * @author tanyaofei + * @since 2024/8/13 + **/ +@Getter +@AllArgsConstructor +public enum FeatureKey implements Translatable, Singletons { + + /** + * 是否具有碰撞箱 + */ + collidable( + "fakeplayer.config.collidable", + List.of(Permission.config), + List.of("true", "false"), + "true", + faker -> String.valueOf(faker.isCollidable()), + (faker, value) -> faker.setCollidable(Boolean.parseBoolean(value)) + ), + + /** + * 是否无敌 + */ + invulnerable( + "fakeplayer.config.invulnerable", + List.of(Permission.config), + List.of("true", "false"), + "true", + faker -> String.valueOf(faker.isInvulnerable()), + (faker, value) -> faker.setInvulnerable(Boolean.parseBoolean(value)) + ), + + /** + * 是否自动看向实体 + */ + look_at_entity( + "fakeplayer.config.look_at_entity", + List.of(Permission.config), + List.of("true", "false"), + "false", + faker -> String.valueOf(actionManager.get().hasActiveAction(faker, ActionType.LOOK_AT_NEAREST_ENTITY)), + (faker, value) -> { + if (Boolean.parseBoolean(value)) { + actionManager.get().setAction(faker, ActionType.LOOK_AT_NEAREST_ENTITY, ActionSetting.continuous()); + } else { + actionManager.get().setAction(faker, ActionType.LOOK_AT_NEAREST_ENTITY, ActionSetting.stop()); + } + } + ), + + /** + * 是否能够拾取物品 + */ + pickup_items( + "fakeplayer.config.pickup_items", + List.of(Permission.config), + List.of("true", "false"), + "true", + faker -> String.valueOf(faker.getCanPickupItems()), + (faker, value) -> faker.setCanPickupItems(Boolean.parseBoolean(value)) + ), + + /** + * 是否使用皮肤 + */ + skin( + "fakeplayer.config.skin", + List.of(Permission.config), + List.of("true", "false"), + "true", + null, + null + ), + + /** + * 是否自动补货 + */ + replenish( + "fakeplayer.config.replenish", + List.of(Permission.config, Permission.replenish), + List.of("true", "false"), + "false", + faker -> String.valueOf(replenishManager.get().isReplenish(faker)), + (faker, value) -> replenishManager.get().setReplenish(faker, Boolean.parseBoolean(value)) + ), + + /** + * 是否自动钓鱼 + */ + autofish( + "fakeplayer.config.autofish", + List.of(Permission.config, Permission.autofish), + List.of("true", "false"), + "false", + faker -> String.valueOf(autofishManager.get().isAutofish(faker)), + (faker, value) -> autofishManager.get().setAutofish(faker, Boolean.parseBoolean(value)) + ), + ; + + @NotNull + final String translationKey; + + @NotNull + final List permissions; + + @NotNull + final List options; + + @NotNull + final String defaultOption; + + @Nullable + final Function detector; + + @Nullable + final BiConsumer modifier; + + + @Override + public @NotNull String translationKey() { + return this.translationKey; + } + + public boolean hasDetector() { + return this.detector != null; + } + + public boolean hasModifier() { + return this.modifier != null; + } + + public boolean testPermissions(@NotNull CommandSender sender) { + if (this.permissions.isEmpty()) { + return true; + } + + for (var permission : this.permissions) { + if (!sender.hasPermission(permission)) { + return false; + } + } + + return true; + } + + +} diff --git a/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/repository/model/Singletons.java b/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/repository/model/Singletons.java new file mode 100644 index 0000000..b4269bf --- /dev/null +++ b/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/repository/model/Singletons.java @@ -0,0 +1,21 @@ +package io.github.hello09x.fakeplayer.core.repository.model; + +import io.github.hello09x.devtools.core.utils.SingletonSupplier; +import io.github.hello09x.fakeplayer.core.Main; +import io.github.hello09x.fakeplayer.core.manager.FakeplayerAutofishManager; +import io.github.hello09x.fakeplayer.core.manager.FakeplayerReplenishManager; +import io.github.hello09x.fakeplayer.core.manager.action.ActionManager; + +import java.util.function.Supplier; + +/** + * @author tanyaofei + * @since 2024/8/13 + **/ +public interface Singletons { + + Supplier actionManager = new SingletonSupplier<>(() -> Main.getInjector().getInstance(ActionManager.class)); + Supplier replenishManager = new SingletonSupplier<>(() -> Main.getInjector().getInstance(FakeplayerReplenishManager.class)); + Supplier autofishManager = new SingletonSupplier<>(() -> Main.getInjector().getInstance(FakeplayerAutofishManager.class)); + +} diff --git a/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/repository/model/UserConfig.java b/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/repository/model/UserConfig.java index 4edcfaf..b2b1e09 100644 --- a/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/repository/model/UserConfig.java +++ b/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/repository/model/UserConfig.java @@ -1,14 +1,21 @@ package io.github.hello09x.fakeplayer.core.repository.model; +import org.jetbrains.annotations.NotNull; + +import java.util.UUID; + public record UserConfig( Integer id, - String playerId, + @NotNull + UUID playerId, - String key, + @NotNull + FeatureKey key, + @NotNull String value ) { diff --git a/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/repository/model/UserConfigRowMapper.java b/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/repository/model/UserConfigRowMapper.java index de0fa88..1f919f1 100644 --- a/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/repository/model/UserConfigRowMapper.java +++ b/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/repository/model/UserConfigRowMapper.java @@ -6,6 +6,7 @@ import org.jetbrains.annotations.Nullable; import java.sql.ResultSet; import java.sql.SQLException; +import java.util.UUID; /** * @author tanyaofei @@ -19,8 +20,8 @@ public class UserConfigRowMapper implements RowMapper { public @Nullable UserConfig mapRow(@NotNull ResultSet rs, int rowNum) throws SQLException { return new UserConfig( rs.getInt("id"), - rs.getString("player_id"), - rs.getString("key"), + UUID.fromString(rs.getString("player_id")), + FeatureKey.valueOf(rs.getString("key")), rs.getString("value") ); } diff --git a/fakeplayer-core/src/main/resources/config.yml b/fakeplayer-core/src/main/resources/config.yml index 7c8b2ee..a058d40 100644 --- a/fakeplayer-core/src/main/resources/config.yml +++ b/fakeplayer-core/src/main/resources/config.yml @@ -252,6 +252,17 @@ allow-commands: - '' - '' +# Default Features of fake players +# 默认假人特性 +default-features: + collidable: true + pickup_items: true + skin: true + look_at_entity: false + invulnerable: false + replenish: false + autofish: false + # 检测更新 # 仅仅是检测, 并不会帮你下载 diff --git a/fakeplayer-core/src/main/resources/message/message.properties b/fakeplayer-core/src/main/resources/message/message.properties index c55516f..4cb5615 100644 --- a/fakeplayer-core/src/main/resources/message/message.properties +++ b/fakeplayer-core/src/main/resources/message/message.properties @@ -16,7 +16,7 @@ fakeplayer.command.cmd.error.execute-failed=Failed to execute the command. Pleas fakeplayer.command.cmd.error.fakeplayer-has-no-permission={0} doesn't have permission fakeplayer.command.cmd.error.no-permission=You don't have permission fakeplayer.command.config.description=Check or change your personal config -fakeplayer.command.config.set.error.invalid-option=Unknown option +fakeplayer.command.config.set.error.invalid-key=Unknown config fakeplayer.command.config.set.error.invalid-value=Unknown value fakeplayer.command.config.set.error.no-permission=You don't have permission to change this config fakeplayer.command.config.set.success={0} changed to {1}, it will take effect the next time you spawn a fake player diff --git a/fakeplayer-core/src/main/resources/message/message_zh.properties b/fakeplayer-core/src/main/resources/message/message_zh.properties index dca8482..89bf840 100644 --- a/fakeplayer-core/src/main/resources/message/message_zh.properties +++ b/fakeplayer-core/src/main/resources/message/message_zh.properties @@ -16,7 +16,7 @@ fakeplayer.command.cmd.error.execute-failed=\u6267\u884C\u547D\u4EE4\u5931\u8D25 fakeplayer.command.cmd.error.fakeplayer-has-no-permission={0} \u6CA1\u6709\u6743\u9650\u6267\u884C\u6B64\u547D\u4EE4 fakeplayer.command.cmd.error.no-permission=\u6CA1\u6709\u6743\u9650\u6267\u884C\u6B64\u547D\u4EE4 fakeplayer.command.config.description=\u67E5\u770B\u6216\u8005\u914D\u7F6E\u4E2A\u4EBA\u8BBE\u7F6E -fakeplayer.command.config.set.error.invalid-option=\u672A\u77E5\u914D\u7F6E\u9879 +fakeplayer.command.config.set.error.invalid-key=\u672A\u77E5\u914D\u7F6E\u9879 fakeplayer.command.config.set.error.invalid-value=\u672A\u77E5\u914D\u7F6E\u503C fakeplayer.command.config.set.error.no-permission=\u4F60\u6CA1\u6709\u6743\u9650\u4FEE\u6539\u8FD9\u9879\u914D\u7F6E fakeplayer.command.config.set.success={0} \u53D8\u66F4\u4E3A {1}, \u4E0B\u6B21\u53EC\u5524\u5047\u4EBA\u65F6\u751F\u6548 diff --git a/fakeplayer-core/src/main/resources/message/message_zh_HK.properties b/fakeplayer-core/src/main/resources/message/message_zh_HK.properties index 838ab39..c1dc770 100644 --- a/fakeplayer-core/src/main/resources/message/message_zh_HK.properties +++ b/fakeplayer-core/src/main/resources/message/message_zh_HK.properties @@ -16,7 +16,7 @@ fakeplayer.command.cmd.error.execute-failed=\u57F7\u884C\u6307\u4EE4\u5931\u6557 fakeplayer.command.cmd.error.fakeplayer-has-no-permission={0} \u5187\u6B0A\u9650\u57F7\u884C\u6B64\u6307\u4EE4 fakeplayer.command.cmd.error.no-permission=\u5187\u6B0A\u9650\u57F7\u884C\u6B64\u6307\u4EE4 fakeplayer.command.config.description=\u67E5\u770B\u500B\u4EBA\u914D\u7F6E -fakeplayer.command.config.set.error.invalid-option=\u672A\u77E5\u914D\u7F6E\u9805 +fakeplayer.command.config.set.error.invalid-key=\u672A\u77E5\u914D\u7F6E\u9805 fakeplayer.command.config.set.error.invalid-value=\u672A\u77E5\u914D\u7F6E\u503C fakeplayer.command.config.set.error.no-permission=\u4F60\u5187\u6B0A\u9650\u4FEE\u6539\u6B64\u914D\u7F6E fakeplayer.command.config.set.success={0} \u8B8A\u66F4\u70BA {1}, \u4E0B\u6B21\u53EC\u559A\u5047\u4EBA\u6642\u751F\u6548 diff --git a/fakeplayer-core/src/main/resources/message/message_zh_TW.properties b/fakeplayer-core/src/main/resources/message/message_zh_TW.properties index 1e056e3..f53e2ff 100644 --- a/fakeplayer-core/src/main/resources/message/message_zh_TW.properties +++ b/fakeplayer-core/src/main/resources/message/message_zh_TW.properties @@ -16,7 +16,7 @@ fakeplayer.command.cmd.error.execute-failed=\u57F7\u884C\u547D\u4EE4\u5931\u6557 fakeplayer.command.cmd.error.fakeplayer-has-no-permission={0} \u6C92\u6709\u6B0A\u9650\u57F7\u884C\u6B64\u547D\u4EE4 fakeplayer.command.cmd.error.no-permission=\u6C92\u6709\u6B0A\u9650\u57F7\u884C\u6B64\u547D\u4EE4 fakeplayer.command.config.description=\u67E5\u770B\u6216\u8005\u914D\u7F6E\u500B\u4EBA\u8A2D\u7F6E -fakeplayer.command.config.set.error.invalid-option=\u672A\u77E5\u914D\u7F6E\u9805 +fakeplayer.command.config.set.error.invalid-key=\u672A\u77E5\u914D\u7F6E\u9805 fakeplayer.command.config.set.error.invalid-value=\u672A\u77E5\u914D\u7F6E\u503C fakeplayer.command.config.set.error.no-permission=\u4F60\u6C92\u6709\u6B0A\u9650\u4FEE\u6539\u9019\u9805\u914D\u7F6E fakeplayer.command.config.set.success={0} \u8B8A\u66F4\u70BA {1}, \u4E0B\u6B21\u53EC\u559A\u5047\u4EBA\u6642\u751F\u6548