mirror of
https://github.com/tanyaofei/minecraft-fakeplayer.git
synced 2025-07-13 21:02:27 +08:00
default-features config
This commit is contained in:
parent
11b9326090
commit
859519eb3f
@ -1,7 +1,12 @@
|
||||
package io.github.hello09x.fakeplayer.api.spi;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public interface ActionTicker {
|
||||
|
||||
@NotNull
|
||||
ActionSetting getSetting();
|
||||
|
||||
/**
|
||||
* 时刻计算
|
||||
*
|
||||
|
@ -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());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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<Object>> config(@NotNull String nodeName) {
|
||||
return config(nodeName, null);
|
||||
public static @NotNull Argument<FeatureKey> configKey(@NotNull String nodeName) {
|
||||
return configKey(nodeName, ignored -> true);
|
||||
}
|
||||
|
||||
public static @NotNull Argument<Config<Object>> config(@NotNull String nodeName, @Nullable Predicate<Config<?>> predicate) {
|
||||
public static @NotNull Argument<FeatureKey> configKey(@NotNull String nodeName, @NotNull Predicate<FeatureKey> predicate) {
|
||||
return new CustomArgument<>(new StringArgument(nodeName), info -> {
|
||||
var arg = info.currentInput();
|
||||
Config<Object> 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<Object> configValue(@NotNull String configNodeName, @NotNull String nodeName) {
|
||||
return new CustomArgument<>(new StringArgument(nodeName), info -> {
|
||||
@SuppressWarnings("unchecked")
|
||||
var config = Objects.requireNonNull((Config<Object>) info.previousArgs().get(configNodeName));
|
||||
|
||||
public static @NotNull Argument<String> configValue(@NotNull String configKeyNodeName, @NotNull String nodeName) {
|
||||
return new CustomArgument<String, String>(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();
|
||||
})));
|
||||
}
|
||||
|
||||
|
@ -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<Object>) 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));
|
||||
});
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
@ -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<Object>) 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));
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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<Component>();
|
||||
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);
|
||||
|
@ -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<FeatureKey, String> 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"));
|
||||
|
@ -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);
|
||||
|
@ -12,6 +12,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
* @param replenish 自动补货
|
||||
*/
|
||||
public record SpawnOption(
|
||||
|
||||
@NotNull
|
||||
Location spawnAt,
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取配置值
|
||||
* <p>
|
||||
* 如果玩家曾经设置过但随后没有了权限, 则返回默认值
|
||||
* </p>
|
||||
*
|
||||
* @param player 玩家
|
||||
* @param config 配置项
|
||||
* @return 配置值
|
||||
*/
|
||||
public <T> T getConfig(@NotNull Player player, @NotNull Config<T> 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取玩家所有配置项
|
||||
* <p>
|
||||
* 如果玩家曾经设置过但随后没有了权限, 则不会包含在其中
|
||||
* </p>
|
||||
*
|
||||
* @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<Config<?>, 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取配置值
|
||||
* <ul>
|
||||
* <li>如果玩家曾经设置过但随后没有了权限, 则为默认值</li>
|
||||
* <li>如果不是玩家, 则为默认值</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param sender 玩家
|
||||
* @param config 配置项
|
||||
* @return 配置值
|
||||
*/
|
||||
public <T> T getConfig(@NotNull CommandSender sender, @NotNull Config<T> config) {
|
||||
if (sender instanceof Player p) {
|
||||
return this.getConfig(p, config);
|
||||
}
|
||||
return config.defaultValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置配置值
|
||||
*
|
||||
* @param player 玩家
|
||||
* @param config 配置
|
||||
* @param value 配置值
|
||||
*/
|
||||
public <T> boolean setConfig(@NotNull Player player, @NotNull Config<T> 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<Config<?>, Object> values;
|
||||
|
||||
private Configs(@NotNull Map<Config<?>, Object> values) {
|
||||
this.values = values;
|
||||
}
|
||||
|
||||
public <T> T getOrDefault(@NotNull Config<T> key) {
|
||||
var config = values.get(key);
|
||||
if (config == null) {
|
||||
return key.defaultValue();
|
||||
}
|
||||
return key.type().cast(config);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -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,
|
||||
|
@ -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<FeatureKey, Feature> getFeatures(@NotNull CommandSender sender) {
|
||||
Map<FeatureKey, UserConfig> 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, Feature>(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
|
||||
));
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
@ -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<UserConfig> 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<UserConfig> selectByPlayerId(@NotNull UUID playerId) {
|
||||
var sql = "select * from user_config where player_id = ?";
|
||||
return jdbc.query(sql, UserConfigRowMapper.instance, playerId.toString());
|
||||
}
|
||||
|
||||
public <T> int saveOrUpdate(@NotNull UUID playerId, @NotNull Config<T> 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
|
||||
|
@ -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<T>(
|
||||
|
||||
@NotNull
|
||||
String key,
|
||||
|
||||
@NotNull
|
||||
String translationKey,
|
||||
|
||||
@NotNull Class<T> type,
|
||||
|
||||
@NotNull
|
||||
T defaultValue,
|
||||
|
||||
@NotNull
|
||||
List<String> options,
|
||||
|
||||
@Nullable
|
||||
String permission,
|
||||
|
||||
@NotNull
|
||||
Function<String, T> parser,
|
||||
|
||||
@UnknownNullability
|
||||
Accessor<T> accessor
|
||||
|
||||
) implements Translatable {
|
||||
|
||||
private static final Map<String, Config<?>> values = new HashMap<>();
|
||||
private static final SingletonSupplier<FakeplayerAutofishManager> autofishManager = new SingletonSupplier<>(() -> Main.getInjector().getInstance(FakeplayerAutofishManager.class));
|
||||
private static final SingletonSupplier<FakeplayerReplenishManager> replenishManager = new SingletonSupplier<>(() -> Main.getInjector().getInstance(FakeplayerReplenishManager.class));
|
||||
|
||||
public static Config<Boolean> 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<Boolean> 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<Boolean> 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<Boolean> 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<Boolean> skin = build(
|
||||
"skin",
|
||||
"fakeplayer.config.skin",
|
||||
Boolean.class,
|
||||
true,
|
||||
List.of("true", "false"),
|
||||
null,
|
||||
Boolean::valueOf,
|
||||
null
|
||||
);
|
||||
|
||||
/**
|
||||
* 自动补货
|
||||
*/
|
||||
public static Config<Boolean> 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<Boolean> 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 <T> Config<T> valueOf(@NotNull String name) {
|
||||
return (Config<T>) valueOfOpt(name).orElseThrow(() -> new IllegalArgumentException("No config named: " + name));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static @NotNull <T> Optional<Config<T>> valueOfOpt(@NotNull String name) {
|
||||
return Optional.ofNullable((Config<T>) values.get(name));
|
||||
}
|
||||
|
||||
public static @NotNull Config<?>[] values() {
|
||||
return values.values().toArray(Config[]::new);
|
||||
}
|
||||
|
||||
private static <T> Config<T> build(
|
||||
@NotNull String name,
|
||||
@NotNull String translationKey,
|
||||
@NotNull Class<T> type,
|
||||
@NotNull T defaultValue,
|
||||
@NotNull List<String> options,
|
||||
@Nullable String permission,
|
||||
@NotNull Function<String, T> converter,
|
||||
@Nullable Accessor<T> 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<T>(
|
||||
@NotNull Function<Player, T> getter,
|
||||
@NotNull BiConsumer<Player, T> setter
|
||||
) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -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<String> permissions;
|
||||
|
||||
@NotNull
|
||||
final List<String> options;
|
||||
|
||||
@NotNull
|
||||
final String defaultOption;
|
||||
|
||||
@Nullable
|
||||
final Function<Player, String> detector;
|
||||
|
||||
@Nullable
|
||||
final BiConsumer<Player, String> 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;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -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> actionManager = new SingletonSupplier<>(() -> Main.getInjector().getInstance(ActionManager.class));
|
||||
Supplier<FakeplayerReplenishManager> replenishManager = new SingletonSupplier<>(() -> Main.getInjector().getInstance(FakeplayerReplenishManager.class));
|
||||
Supplier<FakeplayerAutofishManager> autofishManager = new SingletonSupplier<>(() -> Main.getInjector().getInstance(FakeplayerAutofishManager.class));
|
||||
|
||||
}
|
@ -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
|
||||
|
||||
) {
|
||||
|
@ -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<UserConfig> {
|
||||
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")
|
||||
);
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
||||
# 检测更新
|
||||
# 仅仅是检测, 并不会帮你下载
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user