修改了 RedisBungeeUtil.java 文件,修复了一些逻辑错误并优化了性能。
This commit is contained in:
parent
1de44ba982
commit
0eb25bcbb0
22
pom.xml
22
pom.xml
|
@ -137,5 +137,27 @@
|
|||
<artifactId>jedis</artifactId>
|
||||
<version>5.2.0</version>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/net.jodah/expiringmap -->
|
||||
<dependency>
|
||||
<groupId>net.jodah</groupId>
|
||||
<artifactId>expiringmap</artifactId>
|
||||
<version>0.5.11</version>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/org.javassist/javassist -->
|
||||
<dependency>
|
||||
<groupId>org.javassist</groupId>
|
||||
<artifactId>javassist</artifactId>
|
||||
<version>3.30.2-GA</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mongodb</groupId>
|
||||
<artifactId>mongodb-driver-sync</artifactId>
|
||||
<version>5.4.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mongodb</groupId>
|
||||
<artifactId>mongodb-driver-reactivestreams</artifactId>
|
||||
<version>5.4.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
|
@ -8,14 +8,12 @@ import com.io.yutian.elementoriginlib.logger.Logger;
|
|||
import com.io.yutian.elementoriginlib.manager.CommandManager;
|
||||
import com.io.yutian.elementoriginlib.redis.RedisIO;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public final class ElementOriginLib extends JavaPlugin {
|
||||
|
||||
private static final org.slf4j.Logger log = LoggerFactory.getLogger(ElementOriginLib.class);
|
||||
private static ElementOriginLib instance;
|
||||
public static final Logger LOGGER = Logger.getLogger(ElementOriginLib.class);
|
||||
|
||||
private static Logger logger = Logger.getLogger(ElementOriginLib.class);
|
||||
private static ElementOriginLib instance;
|
||||
|
||||
private RedisIO redisIO;
|
||||
|
||||
|
@ -39,6 +37,7 @@ public final class ElementOriginLib extends JavaPlugin {
|
|||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
redisIO.close();
|
||||
}
|
||||
|
||||
public void reload() {
|
||||
|
|
|
@ -5,7 +5,7 @@ import com.io.yutian.elementoriginlib.command.argument.ArgumentType;
|
|||
import com.io.yutian.elementoriginlib.command.interfaces.Command;
|
||||
import com.io.yutian.elementoriginlib.command.interfaces.Parameter;
|
||||
import com.io.yutian.elementoriginlib.command.interfaces.SubCommand;
|
||||
import com.io.yutian.elementoriginlib.exception.command.CommandParseException;
|
||||
import com.io.yutian.elementoriginlib.exception.CommandParseException;
|
||||
import com.io.yutian.elementoriginlib.logger.Logger;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
|
@ -20,13 +20,15 @@ public class CommandEntity {
|
|||
|
||||
private String command;
|
||||
private String permission;
|
||||
private List<SenderRequire> senderRequires;
|
||||
|
||||
private List<CommandEntry> childrens = new ArrayList<>();
|
||||
|
||||
public CommandEntity(Object instance, String command, String permission, List<CommandEntry> childrens) {
|
||||
public CommandEntity(Object instance, String command, String permission, List<SenderRequire> senderRequires, List<CommandEntry> childrens) {
|
||||
this.instance = instance;
|
||||
this.command = command;
|
||||
this.permission = permission;
|
||||
this.senderRequires = senderRequires;
|
||||
this.childrens = childrens;
|
||||
}
|
||||
|
||||
|
@ -46,11 +48,23 @@ public class CommandEntity {
|
|||
return permission;
|
||||
}
|
||||
|
||||
public List<SenderRequire> getSenderRequires() {
|
||||
return senderRequires;
|
||||
}
|
||||
|
||||
public List<CommandEntry> getChildrens() {
|
||||
return childrens;
|
||||
}
|
||||
|
||||
public boolean canInvoke(CommandSender sender) {
|
||||
if (senderRequires != null && senderRequires.size() > 0) {
|
||||
for (SenderRequire senderRequire : senderRequires) {
|
||||
if (senderRequire.test(sender)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (childrens.size() == 1 && childrens.get(0).isNodal()) {
|
||||
CommandEntry child = childrens.get(0);
|
||||
return child.canInvoke(sender);
|
||||
|
@ -74,17 +88,18 @@ public class CommandEntity {
|
|||
throw new CommandParseException("类 " + clazz + " 未标注 @Command 注解");
|
||||
}
|
||||
|
||||
// Object instance;
|
||||
// try {
|
||||
// instance = clazz.getConstructor(null).newInstance();
|
||||
// } catch (Exception e) {
|
||||
// e.printStackTrace();
|
||||
// throw new CommandParseException("无法实例化类 "+clazz);
|
||||
// }
|
||||
|
||||
Command commandAnnotation = (Command) clazz.getAnnotation(Command.class);
|
||||
String command = commandAnnotation.value();
|
||||
String permission = commandAnnotation.permission();
|
||||
String[] senderRequireArray = commandAnnotation.senderRequire();
|
||||
List<SenderRequire> senderRequireList = new ArrayList<>();
|
||||
for (String senderRequire : senderRequireArray) {
|
||||
SenderRequire senderRequire1 = SenderRequires.get(senderRequire);
|
||||
if (senderRequire1 == null) {
|
||||
throwParseException(clazz, "使用者权限 " + senderRequire + " 不存在");
|
||||
}
|
||||
senderRequireList.add(SenderRequires.get(senderRequire));
|
||||
}
|
||||
|
||||
List<CommandEntry> allEntries = new ArrayList<>();
|
||||
Map<String, CommandEntry> pathToEntryMap = new HashMap<>();
|
||||
|
@ -153,7 +168,7 @@ public class CommandEntity {
|
|||
return null;
|
||||
}
|
||||
|
||||
return new CommandEntity(instance, command, permission, rootEntries);
|
||||
return new CommandEntity(instance, command, permission, senderRequireList, rootEntries);
|
||||
}
|
||||
|
||||
|
||||
|
@ -222,9 +237,20 @@ public class CommandEntity {
|
|||
Parameter commandArgument = parameter.getAnnotation(Parameter.class);
|
||||
String name = commandArgument.name();
|
||||
String argumentName = name.isEmpty() ? parameter.getName() : name;
|
||||
boolean required = commandArgument.required();
|
||||
if (!required && index < allArgumentsCount - 1) {
|
||||
throwParseException(clazz, "可选参数仅能在最后一个位置中使用");
|
||||
boolean optional = commandArgument.optional();
|
||||
if (optional) {
|
||||
boolean flag = true;
|
||||
for (int i = index; i < allArgumentsCount; i++) {
|
||||
java.lang.reflect.Parameter parameter1 = method.getParameters()[i];
|
||||
Parameter parameterAnnotation = parameter.getAnnotation(Parameter.class);
|
||||
if (!parameterAnnotation.optional()) {
|
||||
flag = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!flag) {
|
||||
throwParseException(clazz, "可选参数错误, 后续参数必须都是是可选参数");
|
||||
}
|
||||
}
|
||||
String defaultValue = commandArgument.defaultValue();
|
||||
String suggestionType = commandArgument.suggestionType();
|
||||
|
@ -242,7 +268,7 @@ public class CommandEntity {
|
|||
argument.suggest(suggest);
|
||||
}
|
||||
}
|
||||
if (!required) {
|
||||
if (optional) {
|
||||
argument.optional(defaultValue);
|
||||
}
|
||||
arguments.add(argument);
|
||||
|
|
|
@ -6,6 +6,8 @@ public interface ICommandManager {
|
|||
|
||||
String getName();
|
||||
|
||||
String getPluginId();
|
||||
|
||||
List<CommandEntity> getCommandEntities();
|
||||
|
||||
}
|
||||
|
|
|
@ -65,6 +65,11 @@ public class SimpleCommandManager implements ICommandManager {
|
|||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPluginId() {
|
||||
return name.toLowerCase();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<CommandEntity> getCommandEntities() {
|
||||
|
|
|
@ -8,6 +8,7 @@ import java.util.HashMap;
|
|||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class Suggests {
|
||||
|
||||
|
@ -41,6 +42,51 @@ public class Suggests {
|
|||
suggests.remove(name);
|
||||
}
|
||||
|
||||
public static Suggest createEnumSuggest(Class<? extends Enum> enumClass) {
|
||||
return new EnumSuggest(enumClass);
|
||||
}
|
||||
|
||||
public static Suggest createListSuggest(Supplier<List<String>> supplier) {
|
||||
return new ListSuggest(supplier);
|
||||
}
|
||||
|
||||
private static class EnumSuggest implements Suggest {
|
||||
|
||||
private List<String> suggestions = new LinkedList<>();
|
||||
private Class<? extends Enum> enumClass;
|
||||
|
||||
public EnumSuggest(Class<? extends Enum> enumClass) {
|
||||
this.enumClass = enumClass;
|
||||
if (enumClass != null && enumClass.isEnum()) {
|
||||
Enum<?>[] constants = enumClass.getEnumConstants();
|
||||
if (constants != null) {
|
||||
for (Enum<?> enumConstant : constants) {
|
||||
suggestions.add(enumConstant.name());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getSuggest() {
|
||||
return suggestions;
|
||||
}
|
||||
}
|
||||
|
||||
private static class ListSuggest implements Suggest {
|
||||
|
||||
private Supplier<List<String>> supplier;
|
||||
|
||||
public ListSuggest(Supplier<List<String>> supplier) {
|
||||
this.supplier = supplier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getSuggest() {
|
||||
return supplier.get();
|
||||
}
|
||||
}
|
||||
|
||||
static {
|
||||
|
||||
registerSuggest("world_list", WORLD_LIST);
|
||||
|
|
|
@ -16,6 +16,8 @@ public class ArgumentType<T> {
|
|||
|
||||
private static final ArgumentType<Double> DOUBLE = new ArgumentType<>("double", StringUtil::isDouble, Double::parseDouble);
|
||||
|
||||
private static final ArgumentType<Float> FLOAT = new ArgumentType<>("float", StringUtil::isFloat, Float::parseFloat);
|
||||
|
||||
private static final ArgumentType<Boolean> BOOLEAN = new ArgumentType<>("boolean", StringUtil::isBoolean, Boolean::parseBoolean);
|
||||
|
||||
private static final ArgumentType<String[]> STRING_ARRAY = new ArgumentType<>("string[]", (s) -> true, (s) -> s.split(","));
|
||||
|
@ -74,6 +76,7 @@ public class ArgumentType<T> {
|
|||
register(String.class, STRING);
|
||||
register(Integer.class, INTEGER);
|
||||
register(Double.class, DOUBLE);
|
||||
register(Float.class, FLOAT);
|
||||
register(Boolean.class, BOOLEAN);
|
||||
register(String[].class, STRING_ARRAY);
|
||||
register(Integer[].class, INTEGER_ARRAY);
|
||||
|
@ -97,20 +100,17 @@ public class ArgumentType<T> {
|
|||
return (ArgumentType<T>) ARGUMENT_TYPES.get(c);
|
||||
}
|
||||
|
||||
private static class EnumArgumentType<T extends Enum<T>> extends ArgumentType<T> {
|
||||
|
||||
private final Class<T> clazz;
|
||||
public static class EnumArgumentType<T extends Enum<T>> extends ArgumentType<T> {
|
||||
|
||||
public EnumArgumentType(String name, Class<T> clazz) {
|
||||
super(name, (s)->{
|
||||
try {
|
||||
Enum.valueOf(clazz, s);
|
||||
Enum.valueOf(clazz, s.toUpperCase());
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}, (s)-> Enum.valueOf(clazz, s));
|
||||
this.clazz = clazz;
|
||||
}, (s)-> Enum.valueOf(clazz, s.toUpperCase()));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -74,12 +74,12 @@ public class CommandHandler implements CommandExecutor, TabCompleter {
|
|||
|
||||
if (!entry.getChildrens().isEmpty()) {
|
||||
fullCommand.append(" ");
|
||||
handleCommand(commandEntity, sender, label, args, entry.getChildrens(), index + 1, fullCommand);
|
||||
handleCommand(commandEntity, sender, label, args, entry.getChildrens(), index, fullCommand);
|
||||
} else {
|
||||
if (!validateArguments(sender, entry.getArguments(), args, index + 1)) {
|
||||
if (!validateArguments(sender, entry.getArguments(), args, index)) {
|
||||
return;
|
||||
}
|
||||
Map<String, ArgumentValue> parsedArguments = parseArgumentValue(sender, entry.getArguments(), args, index + 1);
|
||||
Map<String, ArgumentValue> parsedArguments = parseArgumentValue(sender, entry.getArguments(), args, index);
|
||||
entry.invoke(new CommandContext(commandEntity.getInstance(), fullCommand.toString(), label, sender, parsedArguments));
|
||||
}
|
||||
}
|
||||
|
@ -87,7 +87,7 @@ public class CommandHandler implements CommandExecutor, TabCompleter {
|
|||
private boolean validateArguments(CommandSender sender, List<Argument> arguments, String[] args, int startIndex) {
|
||||
for (int i = 0; i < arguments.size(); i++) {
|
||||
Argument argument = arguments.get(i);
|
||||
int argIndex = startIndex + i;
|
||||
int argIndex = startIndex + i + 1;
|
||||
if (argIndex >= args.length) {
|
||||
if (argument.isOptional()) {
|
||||
continue;
|
||||
|
@ -109,36 +109,26 @@ public class CommandHandler implements CommandExecutor, TabCompleter {
|
|||
Map<String, ArgumentValue> parsedArguments = new HashMap<>();
|
||||
List<Object> methodParams = new ArrayList<>();
|
||||
|
||||
int pIndex = startIndex + 1;
|
||||
|
||||
for (int argIndex = 0; argIndex < arguments.size(); argIndex++) {
|
||||
Argument argument = arguments.get(argIndex);
|
||||
if (argIndex >= args.length) {
|
||||
if (!argument.isOptional()) {
|
||||
sender.sendMessage(Lang.get("command.short-arg", argument.getName()));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
String rawValue = null;
|
||||
if (argument.isOptional() && argIndex >= args.length) {
|
||||
if (argument.isOptional() && pIndex >= args.length) {
|
||||
rawValue = argument.getDefaultValue();
|
||||
} else {
|
||||
rawValue = args[argIndex + startIndex];
|
||||
}
|
||||
if (!argument.getArgumentsType().test(rawValue)) {
|
||||
sender.sendMessage(Lang.get("command.error-arg", argIndex + 1, rawValue));
|
||||
return null;
|
||||
rawValue = args[pIndex];
|
||||
}
|
||||
Object parsedValue = argument.getArgumentsType().get(rawValue);
|
||||
parsedArguments.put(argument.getName(), new ArgumentValue(parsedValue));
|
||||
|
||||
methodParams.add(parsedValue);
|
||||
pIndex++;
|
||||
}
|
||||
return parsedArguments;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
long startTime = System.currentTimeMillis();
|
||||
execute(sender, label, args);
|
||||
return true;
|
||||
}
|
||||
|
@ -161,21 +151,23 @@ public class CommandHandler implements CommandExecutor, TabCompleter {
|
|||
}
|
||||
|
||||
CommandEntity commandEntity = entityOptional.get();
|
||||
List<CommandEntry> entries = commandEntity.getChildrens();
|
||||
|
||||
if (entries.isEmpty()) {
|
||||
if (commandEntity == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
int depth = args.length;
|
||||
String currentArg = args[depth - 1];
|
||||
int index = depth - 1;
|
||||
|
||||
return getSuggestions(sender, entries, args, 0, depth - 1, currentArg);
|
||||
String currentArg = args[index];
|
||||
return getSuggestions(sender, commandEntity, args, 0, index, currentArg);
|
||||
}
|
||||
|
||||
|
||||
private List<String> getSuggestions(CommandSender sender, List<CommandEntry> entries, String[] args, int start, int currentDepth, String currentArg) {
|
||||
private List<String> getSuggestions(CommandSender sender, CommandEntity commandEntity, String[] args, int start, int currentDepth, String currentArg) {
|
||||
|
||||
CommandEntry commandEntry = null;
|
||||
List<CommandEntry> entries = commandEntity.getChildrens();
|
||||
|
||||
for (int i = start; i < currentDepth; i++) {
|
||||
String arg = args[i];
|
||||
|
@ -192,10 +184,14 @@ public class CommandHandler implements CommandExecutor, TabCompleter {
|
|||
entries = commandEntry.getChildrens();
|
||||
}
|
||||
|
||||
int pIndex = 2;
|
||||
|
||||
if (commandEntry != null && commandEntry.isNodal()) {
|
||||
pIndex = 1;
|
||||
}
|
||||
if (entries.size() == 0) {
|
||||
List<Argument> arguments = commandEntry.getArguments();
|
||||
int index = (int) (currentDepth - commandEntry.getDepth() - 2);
|
||||
int index = (int) (currentDepth - commandEntry.getDepth() - pIndex);
|
||||
if (index >= arguments.size()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
|
|
@ -13,4 +13,6 @@ public @interface Command {
|
|||
|
||||
String permission() default "command.elementoriginlib.default";
|
||||
|
||||
String[] senderRequire() default { "console", "player" };
|
||||
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ public @interface Parameter {
|
|||
|
||||
String name() default "";
|
||||
|
||||
boolean required() default true;
|
||||
boolean optional() default false;
|
||||
|
||||
String defaultValue() default "";
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ public class CommandHelp {
|
|||
}
|
||||
|
||||
@SubCommand(nodal = true)
|
||||
public void help(CommandContext commandContext, @Parameter(required = false, defaultValue = "1") int page) {
|
||||
public void help(CommandContext commandContext, @Parameter(optional = true, defaultValue = "1") int page) {
|
||||
String alias = commandContext.getLabel();
|
||||
String commandAlias = alias != null ? alias : commandContext.getLabel();
|
||||
CommandSender sender = commandContext.getSender();
|
||||
|
@ -87,6 +87,9 @@ public class CommandHelp {
|
|||
}
|
||||
}
|
||||
Optional<String> optional = Lang.getOptional("command."+command.getCommand()+".description");
|
||||
if (!optional.isPresent()) {
|
||||
optional = Lang.getOptional(commandManager.getPluginId()+".command."+command.getCommand()+".description");
|
||||
}
|
||||
if (optional.isPresent()) {
|
||||
stringBuilder.append(" ");
|
||||
stringBuilder.append("§7- §f"+ optional.get());
|
||||
|
|
|
@ -7,6 +7,13 @@ public class OriginLibConfig {
|
|||
private String redisBungeeNetworkId;
|
||||
private String redisBungeeProxyId;
|
||||
|
||||
private String mongoDbHost;
|
||||
private int mongoDbPort;
|
||||
private String mongoDbDatabase;
|
||||
private String mongoDbUsername;
|
||||
private String mongoDbPassword;
|
||||
|
||||
|
||||
public void load(FileConfiguration config) {
|
||||
redisBungeeNetworkId = config.getString("redisBungeeNetworkId");
|
||||
redisBungeeProxyId = config.getString("redisBungeeProxyId");
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package com.io.yutian.elementoriginlib.exception.command;
|
||||
package com.io.yutian.elementoriginlib.exception;
|
||||
|
||||
public class CommandParseException extends RuntimeException {
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.io.yutian.elementoriginlib.exception.itemstat;
|
||||
package com.io.yutian.elementoriginlib.exception;
|
||||
|
||||
public class ItemStatDataLoadException extends RuntimeException {
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.expiringmap;
|
||||
|
||||
/**
|
||||
* Loads entries on demand.
|
||||
*
|
||||
* @param <K> Key type
|
||||
* @param <V> Value type
|
||||
*/
|
||||
public interface EntryLoader<K, V> {
|
||||
/**
|
||||
* Called to load a new value for the {@code key} into an expiring map.
|
||||
*
|
||||
* @param key to load a value for
|
||||
* @return new value to load
|
||||
*/
|
||||
V load(K key);
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.expiringmap;
|
||||
|
||||
/**
|
||||
* A listener for expired object events.
|
||||
*
|
||||
* @param <K> Key type
|
||||
* @param <V> Value type
|
||||
*/
|
||||
public interface ExpirationListener<K, V> {
|
||||
/**
|
||||
* Called when a map entry expires.
|
||||
*
|
||||
* @param key Expired key
|
||||
* @param value Expired value
|
||||
*/
|
||||
void expired(K key, V value);
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.expiringmap;
|
||||
|
||||
/**
|
||||
* Determines how ExpiringMap entries should be expired.
|
||||
*/
|
||||
public enum ExpirationPolicy {
|
||||
/**
|
||||
* Expires entries based on when they were last accessed
|
||||
*/
|
||||
ACCESSED,
|
||||
/**
|
||||
* Expires entries based on when they were created
|
||||
*/
|
||||
CREATED;
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.expiringmap;
|
||||
|
||||
/**
|
||||
* Loads entries on demand, with control over each value's expiry duration (i.e. variable expiration).
|
||||
*
|
||||
* @param <K> Key type
|
||||
* @param <V> Value type
|
||||
*/
|
||||
public interface ExpiringEntryLoader<K, V> {
|
||||
/**
|
||||
* Called to load a new value for the {@code key} into an expiring map.
|
||||
*
|
||||
* @param key to load a value for
|
||||
* @return contains new value to load along with its expiry duration
|
||||
*/
|
||||
ExpiringValue<V> load(K key);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -1,122 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.expiringmap;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* A value which should be stored in an {@link ExpiringMap} with optional control over its expiration.
|
||||
*
|
||||
* @param <V> the type of value being stored
|
||||
*/
|
||||
public final class ExpiringValue<V> {
|
||||
private static final long UNSET_DURATION = -1L;
|
||||
private final V value;
|
||||
private final ExpirationPolicy expirationPolicy;
|
||||
private final long duration;
|
||||
private final TimeUnit timeUnit;
|
||||
|
||||
/**
|
||||
* Creates an ExpiringValue to be stored in an {@link ExpiringMap}. The map's default values for
|
||||
* {@link ExpirationPolicy expiration policy} and {@link ExpiringMap#getExpiration()} expiration} will be used.
|
||||
*
|
||||
* @param value the value to store
|
||||
* @see ExpiringMap#put(Object, Object)
|
||||
*/
|
||||
public ExpiringValue(V value) {
|
||||
this(value, UNSET_DURATION, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an ExpiringValue to be stored in an {@link ExpiringMap}. The map's default
|
||||
* {@link ExpiringMap#getExpiration()} expiration} will be used.
|
||||
*
|
||||
* @param value the value to store
|
||||
* @param expirationPolicy the expiration policy for the value
|
||||
* @see ExpiringMap#put(Object, Object, ExpirationPolicy)
|
||||
*/
|
||||
public ExpiringValue(V value, ExpirationPolicy expirationPolicy) {
|
||||
this(value, UNSET_DURATION, null, expirationPolicy);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an ExpiringValue to be stored in an {@link ExpiringMap}. The map's default {@link ExpirationPolicy
|
||||
* expiration policy} will be used.
|
||||
*
|
||||
* @param value the value to store
|
||||
* @param duration the length of time after an entry is created that it should be removed
|
||||
* @param timeUnit the unit that {@code duration} is expressed in
|
||||
* @throws NullPointerException on null timeUnit
|
||||
* @see ExpiringMap#put(Object, Object, long, TimeUnit)
|
||||
*/
|
||||
public ExpiringValue(V value, long duration, TimeUnit timeUnit) {
|
||||
this(value, duration, timeUnit, null);
|
||||
if (timeUnit == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an ExpiringValue to be stored in an {@link ExpiringMap}.
|
||||
*
|
||||
* @param value the value to store
|
||||
* @param duration the length of time after an entry is created that it should be removed
|
||||
* @param timeUnit the unit that {@code duration} is expressed in
|
||||
* @param expirationPolicy the expiration policy for the value
|
||||
* @throws NullPointerException on null timeUnit
|
||||
* @see ExpiringMap#put(Object, Object, ExpirationPolicy, long, TimeUnit)
|
||||
*/
|
||||
public ExpiringValue(V value, ExpirationPolicy expirationPolicy, long duration, TimeUnit timeUnit) {
|
||||
this(value, duration, timeUnit, expirationPolicy);
|
||||
if (timeUnit == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
}
|
||||
|
||||
private ExpiringValue(V value, long duration, TimeUnit timeUnit, ExpirationPolicy expirationPolicy) {
|
||||
this.value = value;
|
||||
this.expirationPolicy = expirationPolicy;
|
||||
this.duration = duration;
|
||||
this.timeUnit = timeUnit;
|
||||
}
|
||||
|
||||
public V getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public ExpirationPolicy getExpirationPolicy() {
|
||||
return expirationPolicy;
|
||||
}
|
||||
|
||||
public long getDuration() {
|
||||
return duration;
|
||||
}
|
||||
|
||||
public TimeUnit getTimeUnit() {
|
||||
return timeUnit;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return value != null ? value.hashCode() : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ExpiringValue<?> that = (ExpiringValue<?>) o;
|
||||
return !(value != null ? !value.equals(that.value) : that.value != null)
|
||||
&& expirationPolicy == that.expirationPolicy && duration == that.duration && timeUnit == that.timeUnit;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ExpiringValue{" + "value=" + value + ", expirationPolicy=" + expirationPolicy + ", duration=" + duration
|
||||
+ ", timeUnit=" + timeUnit + '}';
|
||||
}
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.expiringmap.internal;
|
||||
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
/**
|
||||
* @author Jonathan Halterman
|
||||
*/
|
||||
public final class Assert {
|
||||
private Assert() {
|
||||
}
|
||||
|
||||
public static <T> T notNull(T reference, String parameterName) {
|
||||
if (reference == null)
|
||||
throw new NullPointerException(parameterName + " cannot be null");
|
||||
return reference;
|
||||
}
|
||||
|
||||
public static void operation(boolean condition, String message) {
|
||||
if (!condition)
|
||||
throw new UnsupportedOperationException(message);
|
||||
}
|
||||
|
||||
public static void state(boolean expression, String errorMessageFormat, Object... args) {
|
||||
if (!expression)
|
||||
throw new IllegalStateException(String.format(errorMessageFormat, args));
|
||||
}
|
||||
|
||||
public static void element(Object element, Object key) {
|
||||
if (element == null)
|
||||
throw new NoSuchElementException(key.toString());
|
||||
}
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.expiringmap.internal;
|
||||
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* Named thread factory.
|
||||
*/
|
||||
public class NamedThreadFactory implements ThreadFactory {
|
||||
private final AtomicInteger threadNumber = new AtomicInteger(1);
|
||||
private final String nameFormat;
|
||||
|
||||
/**
|
||||
* Creates a thread factory that names threads according to the {@code nameFormat} by supplying a
|
||||
* single argument to the format representing the thread number.
|
||||
*/
|
||||
public NamedThreadFactory(String nameFormat) {
|
||||
this.nameFormat = nameFormat;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Thread newThread(Runnable r) {
|
||||
Thread thread = new Thread(r, String.format(nameFormat, threadNumber.getAndIncrement()));
|
||||
thread.setDaemon(true);
|
||||
return thread;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
package com.io.yutian.elementoriginlib.gui;
|
||||
|
||||
import com.io.yutian.elementoriginlib.util.ItemStackBuilder;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.event.ClickEvent;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.event.inventory.InventoryCloseEvent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class DebugGui extends Gui {
|
||||
|
||||
private Set<Integer> cachedSlots = new HashSet<>();
|
||||
|
||||
public DebugGui(Player player, int size) {
|
||||
super(player, Component.text("Debug Gui"), size);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close(InventoryCloseEvent event) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int i = 0;
|
||||
List<Integer> list = new ArrayList<>(cachedSlots);
|
||||
list.sort(Integer::compareTo);
|
||||
for (int slot : list) {
|
||||
sb.append(slot);
|
||||
if (i < list.size() - 1) {
|
||||
sb.append(", ");
|
||||
}
|
||||
i++;
|
||||
}
|
||||
player.sendMessage(Component.text("§b["+sb.toString()+"]").clickEvent(ClickEvent.clickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, sb.toString())).hoverEvent(Component.text("§f§l[点击复制]")));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handler(Player player, int slot, InventoryClickEvent event) {
|
||||
if (slot < inventory.getSize()) {
|
||||
if (!cachedSlots.contains(slot)) {
|
||||
cachedSlots.add(slot);
|
||||
inventory.setItem(slot, new ItemStackBuilder(Material.SLIME_BALL).setDisplayName(" ").setDisplayName("§a"+slot).build());
|
||||
}
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -13,7 +13,7 @@ import org.bukkit.event.inventory.InventoryClickEvent;
|
|||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class Gui extends IGui {
|
||||
public abstract class Gui extends IGui {
|
||||
|
||||
public Map<Integer, Button> buttons = new HashMap<>();
|
||||
|
||||
|
@ -21,10 +21,6 @@ public class Gui extends IGui {
|
|||
super(player, title, size);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handler(Player player, int slot, InventoryClickEvent event) {
|
||||
if (buttons.containsKey(slot)) {
|
||||
|
|
|
@ -38,6 +38,7 @@ public abstract class IGui implements InventoryHolder {
|
|||
}
|
||||
|
||||
public void open() {
|
||||
init();
|
||||
player.openInventory(inventory);
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ import org.bukkit.event.inventory.InventoryClickEvent;
|
|||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class PageGui extends IGui {
|
||||
public abstract class PageGui extends IGui {
|
||||
|
||||
private int page = 1;
|
||||
private int maxPage;
|
||||
|
@ -25,6 +25,13 @@ public class PageGui extends IGui {
|
|||
this.maxPage = maxPage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void open() {
|
||||
init();
|
||||
initButton();
|
||||
player.openInventory(inventory);
|
||||
}
|
||||
|
||||
public void initButton() {
|
||||
initButton(this.page);
|
||||
}
|
||||
|
@ -63,10 +70,6 @@ public class PageGui extends IGui {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handler(Player player, int slot, InventoryClickEvent event) {
|
||||
if (pages.containsKey(page)) {
|
||||
|
|
|
@ -24,16 +24,40 @@ public class TagStatItem {
|
|||
this.builder = new TagStatItemStackBuilder(this);
|
||||
}
|
||||
|
||||
public void setStatData(@NotNull Class<? extends ItemStat> statClass, @NotNull StatData data) {
|
||||
ItemStat itemStat = ItemStats.getItemStat(statClass);
|
||||
if (itemStat == null) {
|
||||
return;
|
||||
}
|
||||
setStatData(itemStat, data);
|
||||
}
|
||||
|
||||
public void setStatData(@NotNull ItemStat stat, @NotNull StatData data) {
|
||||
this.stats.put(stat, data);
|
||||
this.itemStack = builder().build();
|
||||
}
|
||||
|
||||
public void removeStatData(@NotNull Class<? extends ItemStat> statClass) {
|
||||
ItemStat itemStat = ItemStats.getItemStat(statClass);
|
||||
if (itemStat == null) {
|
||||
return;
|
||||
}
|
||||
removeStatData(itemStat);
|
||||
}
|
||||
|
||||
public void removeStatData(@NotNull ItemStat stat) {
|
||||
this.stats.remove(stat);
|
||||
this.itemStack = builder().build();
|
||||
}
|
||||
|
||||
public <S extends StatData> S getStatData(@NotNull Class<? extends ItemStat<S>> statClass) {
|
||||
ItemStat itemStat = ItemStats.getItemStat(statClass);
|
||||
if (itemStat == null) {
|
||||
return null;
|
||||
}
|
||||
return (S) getStatData(itemStat);
|
||||
}
|
||||
|
||||
public <S extends StatData> S getStatData(@NotNull ItemStat<S> stat) {
|
||||
if (!hasStatData(stat)) {
|
||||
stat.load(this);
|
||||
|
@ -41,6 +65,14 @@ public class TagStatItem {
|
|||
return (S) this.stats.get(stat);
|
||||
}
|
||||
|
||||
public boolean hasStatData(@NotNull Class<? extends ItemStat> statClass) {
|
||||
ItemStat itemStat = ItemStats.getItemStat(statClass);
|
||||
if (itemStat == null) {
|
||||
return false;
|
||||
}
|
||||
return hasStatData(itemStat);
|
||||
}
|
||||
|
||||
public boolean hasStatData(@NotNull ItemStat stat) {
|
||||
if (!this.stats.containsKey(stat)) {
|
||||
try {
|
||||
|
|
|
@ -2,13 +2,9 @@ package com.io.yutian.elementoriginlib.item;
|
|||
|
||||
import com.io.yutian.elementoriginlib.tag.ItemProxy;
|
||||
import com.io.yutian.elementoriginlib.tag.TagCompound;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class TagStatItemStackBuilder {
|
||||
|
@ -16,14 +12,12 @@ public class TagStatItemStackBuilder {
|
|||
private final TagStatItem tagStatItem;
|
||||
|
||||
protected ItemStack itemStack;
|
||||
protected ItemMeta itemMeta;
|
||||
|
||||
protected ItemProxy itemProxy;
|
||||
|
||||
public TagStatItemStackBuilder(TagStatItem tagStatItem) {
|
||||
this.tagStatItem = tagStatItem;
|
||||
this.itemStack = tagStatItem.getItemStack();
|
||||
this.itemMeta = itemStack.getItemMeta();
|
||||
this.itemProxy = tagStatItem.getItemProxy();
|
||||
}
|
||||
|
||||
|
@ -37,20 +31,10 @@ public class TagStatItemStackBuilder {
|
|||
return itemStack;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ItemMeta getItemMeta() {
|
||||
return itemMeta;
|
||||
}
|
||||
|
||||
private void buildCompounds() {
|
||||
tagStatItem.getStats().forEach((stat, statData) -> stat.whenApplied(this, statData));
|
||||
itemStack = itemProxy.getItemStack();
|
||||
itemMeta = itemStack.getItemMeta();
|
||||
tagStatItem.getStats().forEach((stat, statData) -> stat.applyMeta(this, statData));
|
||||
List<Component> lores = itemMeta.hasLore() ? itemMeta.lore() : new ArrayList<>();
|
||||
tagStatItem.getStats().forEach((stat, statData) -> stat.whenApplyLore(this, statData, lores));
|
||||
itemMeta.lore(lores);
|
||||
itemStack.setItemMeta(itemMeta);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
@ -58,6 +42,10 @@ public class TagStatItemStackBuilder {
|
|||
return itemProxy;
|
||||
}
|
||||
|
||||
public ItemStack getItemStack() {
|
||||
return itemStack;
|
||||
}
|
||||
|
||||
public TagStatItem getOriginItem() {
|
||||
return tagStatItem;
|
||||
}
|
||||
|
|
|
@ -1,14 +1,11 @@
|
|||
package com.io.yutian.elementoriginlib.item.stat;
|
||||
|
||||
import com.io.yutian.elementoriginlib.exception.itemstat.ItemStatDataLoadException;
|
||||
import com.io.yutian.elementoriginlib.item.TagStatItem;
|
||||
import com.io.yutian.elementoriginlib.item.TagStatItemStackBuilder;
|
||||
import com.io.yutian.elementoriginlib.tag.ItemProxy;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public abstract class ItemStat<S extends StatData> {
|
||||
|
||||
@NotNull
|
||||
|
@ -23,14 +20,9 @@ public abstract class ItemStat<S extends StatData> {
|
|||
|
||||
public abstract void whenApplied(@NotNull TagStatItemStackBuilder itemStackBuilder, @NotNull S statData);
|
||||
|
||||
public abstract S loadAsObject(@NotNull Object value) throws ItemStatDataLoadException;
|
||||
|
||||
public void applyMeta(@NotNull TagStatItemStackBuilder itemStackBuilder, @NotNull S statData) {
|
||||
}
|
||||
|
||||
public void whenApplyLore(@NotNull TagStatItemStackBuilder itemStackBuilder, @NotNull S statData, @NotNull List<String> lores) {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public abstract S getLoadedTag(@NotNull ItemProxy itemProxy);
|
||||
|
||||
|
|
|
@ -4,10 +4,7 @@ import com.io.yutian.elementoriginlib.item.stat.list.IdStat;
|
|||
import com.io.yutian.elementoriginlib.logger.Logger;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
public class ItemStats {
|
||||
|
||||
|
@ -21,13 +18,28 @@ public class ItemStats {
|
|||
|
||||
public static void register(ItemStat itemStat) {
|
||||
Class<? extends ItemStat> clazz = itemStat.getClass();
|
||||
if (itemStats.containsKey(itemStat.getId())) {
|
||||
LOGGER.warn("ItemStat "+clazz.getName()+" 已存在");
|
||||
return;
|
||||
if (isRegistered(itemStat)) {
|
||||
LOGGER.warn("ItemStat "+clazz.getName()+" 已注册,将覆盖原有注册");
|
||||
Set<Class<? extends ItemStat>> removeSet = new HashSet<>();
|
||||
for (Class<? extends ItemStat> clazz1 : itemStats.keySet()) {
|
||||
if (clazz1.getName().equalsIgnoreCase(itemStat.getClass().getName())) {
|
||||
removeSet.add(clazz1);
|
||||
}
|
||||
}
|
||||
removeSet.forEach((aClass -> itemStats.remove(aClass)));
|
||||
}
|
||||
itemStats.put(clazz, itemStat);
|
||||
}
|
||||
|
||||
private static boolean isRegistered(ItemStat itemStat) {
|
||||
for (Class<? extends ItemStat> clazz : itemStats.keySet()) {
|
||||
if (clazz.getName().equalsIgnoreCase(itemStat.getClass().getName())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return itemStats.containsKey(itemStat.getClass());
|
||||
}
|
||||
|
||||
public static void unregister(ItemStat itemStat) {
|
||||
itemStats.remove(itemStat.getId());
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package com.io.yutian.elementoriginlib.item.stat.type;
|
||||
|
||||
import com.io.yutian.elementoriginlib.exception.itemstat.ItemStatDataLoadException;
|
||||
import com.io.yutian.elementoriginlib.item.TagStatItemStackBuilder;
|
||||
import com.io.yutian.elementoriginlib.item.stat.ItemStat;
|
||||
import com.io.yutian.elementoriginlib.item.stat.data.BooleanData;
|
||||
|
@ -9,8 +8,6 @@ import com.io.yutian.elementoriginlib.tag.ItemProxy;
|
|||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public abstract class BooleanStat extends ItemStat<BooleanData> {
|
||||
|
||||
public BooleanStat(@NotNull String id, @NotNull String path) {
|
||||
|
@ -23,32 +20,6 @@ public abstract class BooleanStat extends ItemStat<BooleanData> {
|
|||
itemProxy.editTag(tagCompound1 -> tagCompound1.putByte(getTagPath(), (byte) (statData.getValue() ? 1 : 0)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public BooleanData loadAsObject(@NotNull Object value) throws ItemStatDataLoadException {
|
||||
if (Objects.isNull(value)) {
|
||||
throw new ItemStatDataLoadException("Invalid value: null");
|
||||
}
|
||||
try {
|
||||
if (value instanceof Boolean bool) {
|
||||
return new BooleanData(bool);
|
||||
} else if (value instanceof String arg) {
|
||||
boolean parsed = Boolean.parseBoolean(arg);
|
||||
if (!arg.equalsIgnoreCase("true") && !arg.equalsIgnoreCase("false")) {
|
||||
throw new ItemStatDataLoadException("Invalid boolean string: " + arg);
|
||||
}
|
||||
return new BooleanData(parsed);
|
||||
} else if (value instanceof Byte b) {
|
||||
return new BooleanData(b == 1);
|
||||
} else if (value instanceof Integer i) {
|
||||
return new BooleanData(i == 1);
|
||||
} else {
|
||||
throw new ItemStatDataLoadException("Invalid boolean value: " + value);
|
||||
}
|
||||
} catch (ClassCastException e) {
|
||||
throw new ItemStatDataLoadException("Invalid type: " + value.getClass(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public BooleanData getLoadedTag(@NotNull ItemProxy itemProxy) {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package com.io.yutian.elementoriginlib.item.stat.type;
|
||||
|
||||
import com.io.yutian.elementoriginlib.exception.itemstat.ItemStatDataLoadException;
|
||||
import com.io.yutian.elementoriginlib.item.TagStatItemStackBuilder;
|
||||
import com.io.yutian.elementoriginlib.item.stat.ItemStat;
|
||||
import com.io.yutian.elementoriginlib.item.stat.data.DoubleListData;
|
||||
|
@ -11,9 +10,7 @@ import org.jetbrains.annotations.NotNull;
|
|||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public abstract class DoubleListStat extends ItemStat<DoubleListData> {
|
||||
|
||||
|
@ -29,58 +26,6 @@ public abstract class DoubleListStat extends ItemStat<DoubleListData> {
|
|||
itemProxy.editTag(tagCompound1 -> tagCompound1.put(getTagPath(), tagList));
|
||||
}
|
||||
|
||||
@Override
|
||||
public DoubleListData loadAsObject(@NotNull Object value) throws ItemStatDataLoadException {
|
||||
if (Objects.isNull(value)) {
|
||||
throw new ItemStatDataLoadException("Invalid value: null");
|
||||
}
|
||||
try {
|
||||
if (value instanceof List<?> list) {
|
||||
List<Double> doubleList = new ArrayList<>();
|
||||
for (Object item : list) {
|
||||
if (item instanceof Double d) {
|
||||
doubleList.add(d);
|
||||
} else if (item instanceof String str) {
|
||||
// 如果是 String,尝试将其解析为 Double
|
||||
try {
|
||||
doubleList.add(Double.parseDouble(str));
|
||||
} catch (NumberFormatException e) {
|
||||
throw new ItemStatDataLoadException("Invalid string value for Double: " + str, e);
|
||||
}
|
||||
} else {
|
||||
throw new ItemStatDataLoadException("List contains non-double element: " + item);
|
||||
}
|
||||
}
|
||||
return new DoubleListData(doubleList);
|
||||
} else if (value instanceof double[] array) {
|
||||
List<Double> doubleList = new ArrayList<>();
|
||||
for (double d : array) {
|
||||
doubleList.add(d);
|
||||
}
|
||||
return new DoubleListData(doubleList);
|
||||
} else if (value instanceof Double[] array) {
|
||||
List<Double> doubleList = new ArrayList<>(Arrays.asList(array));
|
||||
return new DoubleListData(doubleList);
|
||||
} else if (value instanceof String str) {
|
||||
List<Double> doubleList = new ArrayList<>();
|
||||
String[] items = str.split(",");
|
||||
for (String item : items) {
|
||||
try {
|
||||
doubleList.add(Double.parseDouble(item.trim()));
|
||||
} catch (NumberFormatException e) {
|
||||
throw new ItemStatDataLoadException("Invalid number format in string: " + item, e);
|
||||
}
|
||||
}
|
||||
return new DoubleListData(doubleList);
|
||||
} else {
|
||||
throw new ItemStatDataLoadException("Invalid value type for DoubleListData: " + value);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new ItemStatDataLoadException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public DoubleListData getLoadedTag(@NotNull ItemProxy itemProxy) {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package com.io.yutian.elementoriginlib.item.stat.type;
|
||||
|
||||
import com.io.yutian.elementoriginlib.exception.itemstat.ItemStatDataLoadException;
|
||||
import com.io.yutian.elementoriginlib.item.TagStatItemStackBuilder;
|
||||
import com.io.yutian.elementoriginlib.item.stat.ItemStat;
|
||||
import com.io.yutian.elementoriginlib.item.stat.data.DoubleData;
|
||||
|
@ -9,8 +8,6 @@ import com.io.yutian.elementoriginlib.tag.ItemProxy;
|
|||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public abstract class DoubleStat extends ItemStat<DoubleData> {
|
||||
|
||||
public DoubleStat(@NotNull String id, @NotNull String path) {
|
||||
|
@ -23,34 +20,6 @@ public abstract class DoubleStat extends ItemStat<DoubleData> {
|
|||
itemProxy.editTag(tagCompound1 -> tagCompound1.putDouble(getTagPath(), statData.getValue()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public DoubleData loadAsObject(@NotNull Object value) throws ItemStatDataLoadException {
|
||||
if (Objects.isNull(value)) {
|
||||
throw new ItemStatDataLoadException("Invalid value: null");
|
||||
}
|
||||
try {
|
||||
if (value instanceof Double d) {
|
||||
return new DoubleData(d);
|
||||
} else if (value instanceof String arg) {
|
||||
try {
|
||||
return new DoubleData(Double.parseDouble(arg));
|
||||
} catch (NumberFormatException e) {
|
||||
throw new ItemStatDataLoadException("Invalid double string: " + arg, e);
|
||||
}
|
||||
} else if (value instanceof Byte b) {
|
||||
return new DoubleData((double) b);
|
||||
} else if (value instanceof Integer i) {
|
||||
return new DoubleData((double) i);
|
||||
} else if (value instanceof Long l) {
|
||||
return new DoubleData((double) l);
|
||||
} else {
|
||||
throw new ItemStatDataLoadException("Invalid double value: " + value);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new ItemStatDataLoadException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public DoubleData getLoadedTag(@NotNull ItemProxy itemProxy) {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package com.io.yutian.elementoriginlib.item.stat.type;
|
||||
|
||||
import com.io.yutian.elementoriginlib.exception.itemstat.ItemStatDataLoadException;
|
||||
import com.io.yutian.elementoriginlib.item.TagStatItemStackBuilder;
|
||||
import com.io.yutian.elementoriginlib.item.stat.ItemStat;
|
||||
import com.io.yutian.elementoriginlib.item.stat.data.EnumListData;
|
||||
|
@ -12,7 +11,6 @@ import org.jetbrains.annotations.Nullable;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
|
||||
public abstract class EnumListStat<E extends Enum> extends ItemStat<EnumListData<E>> {
|
||||
|
@ -32,55 +30,6 @@ public abstract class EnumListStat<E extends Enum> extends ItemStat<EnumListData
|
|||
itemProxy.editTag(tagCompound1 -> tagCompound1.put(getTagPath(), tagList));
|
||||
}
|
||||
|
||||
@Override
|
||||
public EnumListData<E> loadAsObject(@NotNull Object value) throws ItemStatDataLoadException {
|
||||
if (Objects.isNull(value)) {
|
||||
throw new ItemStatDataLoadException("Invalid value: null");
|
||||
}
|
||||
try {
|
||||
if (value instanceof List<?> list) {
|
||||
List<E> enumList = new ArrayList<>();
|
||||
for (Object item : list) {
|
||||
if (item instanceof String str) {
|
||||
try {
|
||||
E enumConstant = (E) Enum.valueOf(clazz, str);
|
||||
enumList.add(enumConstant);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new ItemStatDataLoadException("Invalid enum string: " + str, e);
|
||||
}
|
||||
} else if (item instanceof Integer i) {
|
||||
E[] enumConstants = clazz.getEnumConstants();
|
||||
if (i < 0 || i >= enumConstants.length) {
|
||||
throw new ItemStatDataLoadException("Invalid enum ordinal: " + i);
|
||||
}
|
||||
enumList.add(enumConstants[i]);
|
||||
} else if (item instanceof Enum<?> enumItem) {
|
||||
enumList.add((E) enumItem);
|
||||
} else {
|
||||
throw new ItemStatDataLoadException("Invalid list element type: " + item);
|
||||
}
|
||||
}
|
||||
return new EnumListData<>(enumList);
|
||||
} else if (value instanceof String str) {
|
||||
List<E> enumList = new ArrayList<>();
|
||||
String[] enumNames = str.split(",");
|
||||
for (String enumName : enumNames) {
|
||||
try {
|
||||
E enumConstant = (E) Enum.valueOf(clazz, enumName.trim());
|
||||
enumList.add(enumConstant);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new ItemStatDataLoadException("Invalid enum string: " + enumName, e);
|
||||
}
|
||||
}
|
||||
return new EnumListData<>(enumList);
|
||||
} else {
|
||||
throw new ItemStatDataLoadException("Invalid value type for EnumListData: " + value);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new ItemStatDataLoadException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable EnumListData<E> getLoadedTag(@NotNull ItemProxy itemProxy) {
|
||||
if (!itemProxy.has(getTagPath(), TagList.TYPE_ID)) {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package com.io.yutian.elementoriginlib.item.stat.type;
|
||||
|
||||
import com.io.yutian.elementoriginlib.exception.itemstat.ItemStatDataLoadException;
|
||||
import com.io.yutian.elementoriginlib.item.TagStatItemStackBuilder;
|
||||
import com.io.yutian.elementoriginlib.item.stat.ItemStat;
|
||||
import com.io.yutian.elementoriginlib.item.stat.data.EnumData;
|
||||
|
@ -9,8 +8,6 @@ import com.io.yutian.elementoriginlib.tag.TagString;
|
|||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public abstract class EnumStat<E extends Enum> extends ItemStat<EnumData<E>> {
|
||||
|
||||
private Class<E> clazz;
|
||||
|
@ -26,35 +23,6 @@ public abstract class EnumStat<E extends Enum> extends ItemStat<EnumData<E>> {
|
|||
itemProxy.editTag(tagCompound1 -> tagCompound1.putString(getTagPath(), statData.getValue().name()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public EnumData<E> loadAsObject(@NotNull Object value) throws ItemStatDataLoadException {
|
||||
if (Objects.isNull(value)) {
|
||||
throw new ItemStatDataLoadException("Invalid value: null");
|
||||
}
|
||||
try {
|
||||
if (value instanceof Enum<?> enumValue) {
|
||||
return new EnumData<>((E) enumValue);
|
||||
} else if (value instanceof String str) {
|
||||
try {
|
||||
E enumConstant = (E) Enum.valueOf(clazz, str);
|
||||
return new EnumData<>(enumConstant);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new ItemStatDataLoadException("Invalid enum string: " + str, e);
|
||||
}
|
||||
} else if (value instanceof Integer i) {
|
||||
E[] enumConstants = clazz.getEnumConstants();
|
||||
if (i < 0 || i >= enumConstants.length) {
|
||||
throw new ItemStatDataLoadException("Invalid enum ordinal: " + i);
|
||||
}
|
||||
return new EnumData<>(enumConstants[i]);
|
||||
} else {
|
||||
throw new ItemStatDataLoadException("Invalid value type for EnumData: " + value);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new ItemStatDataLoadException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable EnumData<E> getLoadedTag(@NotNull ItemProxy itemProxy) {
|
||||
return new EnumData(Enum.valueOf(clazz, ((TagString) itemProxy.get(getTagPath())).getString()));
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package com.io.yutian.elementoriginlib.item.stat.type;
|
||||
|
||||
import com.io.yutian.elementoriginlib.exception.itemstat.ItemStatDataLoadException;
|
||||
import com.io.yutian.elementoriginlib.item.TagStatItemStackBuilder;
|
||||
import com.io.yutian.elementoriginlib.item.stat.ItemStat;
|
||||
import com.io.yutian.elementoriginlib.item.stat.data.IntListData;
|
||||
|
@ -12,7 +11,6 @@ import org.jetbrains.annotations.Nullable;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public abstract class IntListStat extends ItemStat<IntListData> {
|
||||
|
||||
|
@ -28,47 +26,6 @@ public abstract class IntListStat extends ItemStat<IntListData> {
|
|||
itemProxy.editTag(tagCompound1 -> tagCompound1.put(getTagPath(), tagList));
|
||||
}
|
||||
|
||||
@Override
|
||||
public IntListData loadAsObject(@NotNull Object value) throws ItemStatDataLoadException {
|
||||
if (Objects.isNull(value)) {
|
||||
throw new ItemStatDataLoadException("Invalid value: null");
|
||||
}
|
||||
try {
|
||||
if (value instanceof List<?> list) {
|
||||
List<Integer> intList = new ArrayList<>();
|
||||
for (Object item : list) {
|
||||
if (item instanceof Integer i) {
|
||||
intList.add(i);
|
||||
} else {
|
||||
throw new ItemStatDataLoadException("List contains non-integer element: " + item);
|
||||
}
|
||||
}
|
||||
return new IntListData(intList);
|
||||
} else if (value instanceof int[] array) {
|
||||
List<Integer> intList = new ArrayList<>();
|
||||
for (int i : array) {
|
||||
intList.add(i);
|
||||
}
|
||||
return new IntListData(intList);
|
||||
} else if (value instanceof String str) {
|
||||
try {
|
||||
List<Integer> intList = new ArrayList<>();
|
||||
String[] items = str.split(",");
|
||||
for (String item : items) {
|
||||
intList.add(Integer.parseInt(item.trim()));
|
||||
}
|
||||
return new IntListData(intList);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new ItemStatDataLoadException("Invalid integer string: " + str, e);
|
||||
}
|
||||
} else {
|
||||
throw new ItemStatDataLoadException("Invalid value type for IntListData: " + value);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new ItemStatDataLoadException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public IntListData getLoadedTag(@NotNull ItemProxy itemProxy) {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package com.io.yutian.elementoriginlib.item.stat.type;
|
||||
|
||||
import com.io.yutian.elementoriginlib.exception.itemstat.ItemStatDataLoadException;
|
||||
import com.io.yutian.elementoriginlib.item.TagStatItemStackBuilder;
|
||||
import com.io.yutian.elementoriginlib.item.stat.ItemStat;
|
||||
import com.io.yutian.elementoriginlib.item.stat.data.IntData;
|
||||
|
@ -9,8 +8,6 @@ import com.io.yutian.elementoriginlib.tag.ItemProxy;
|
|||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public abstract class IntStat extends ItemStat<IntData> {
|
||||
|
||||
public IntStat(@NotNull String id, @NotNull String path) {
|
||||
|
@ -23,48 +20,6 @@ public abstract class IntStat extends ItemStat<IntData> {
|
|||
itemProxy.editTag(tagCompound1 -> tagCompound1.putInt(getTagPath(), statData.getInt()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public IntData loadAsObject(@NotNull Object value) throws ItemStatDataLoadException {
|
||||
if (Objects.isNull(value)) {
|
||||
throw new ItemStatDataLoadException("Invalid value: null");
|
||||
}
|
||||
try {
|
||||
if (value instanceof Integer i) {
|
||||
return new IntData(i);
|
||||
} else if (value instanceof String arg) {
|
||||
try {
|
||||
return new IntData(Integer.parseInt(arg));
|
||||
} catch (NumberFormatException e) {
|
||||
throw new ItemStatDataLoadException("Invalid integer string: " + arg, e);
|
||||
}
|
||||
} else if (value instanceof Byte b) {
|
||||
return new IntData((int) b);
|
||||
} else if (value instanceof Long l) {
|
||||
if (l < Integer.MIN_VALUE || l > Integer.MAX_VALUE) {
|
||||
throw new ItemStatDataLoadException("Long value out of range for integer: " + l);
|
||||
}
|
||||
return new IntData(l.intValue());
|
||||
} else if (value instanceof Double d) {
|
||||
if (d < Integer.MIN_VALUE || d > Integer.MAX_VALUE) {
|
||||
throw new ItemStatDataLoadException("Double value out of range for integer: " + d);
|
||||
}
|
||||
return new IntData((int) d.doubleValue());
|
||||
} else if (value instanceof Float f) {
|
||||
if (f < Integer.MIN_VALUE || f > Integer.MAX_VALUE) {
|
||||
throw new ItemStatDataLoadException("Float value out of range for integer: " + f);
|
||||
}
|
||||
return new IntData((int) f.floatValue());
|
||||
} else {
|
||||
throw new ItemStatDataLoadException("Invalid integer value: " + value);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new ItemStatDataLoadException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public IntData getLoadedTag(@NotNull ItemProxy itemProxy) {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package com.io.yutian.elementoriginlib.item.stat.type;
|
||||
|
||||
import com.io.yutian.elementoriginlib.exception.itemstat.ItemStatDataLoadException;
|
||||
import com.io.yutian.elementoriginlib.item.TagStatItemStackBuilder;
|
||||
import com.io.yutian.elementoriginlib.item.stat.ItemStat;
|
||||
import com.io.yutian.elementoriginlib.item.stat.data.MapData;
|
||||
|
@ -10,7 +9,6 @@ import org.jetbrains.annotations.Nullable;
|
|||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
public class MapStat extends ItemStat<MapData> {
|
||||
|
||||
|
@ -28,30 +26,6 @@ public class MapStat extends ItemStat<MapData> {
|
|||
itemProxy.editTag(tagCompound1 -> tagCompound1.put(getTagPath(), tagCompound));
|
||||
}
|
||||
|
||||
@Override
|
||||
public MapData loadAsObject(@NotNull Object value) throws ItemStatDataLoadException {
|
||||
if (Objects.isNull(value)) {
|
||||
throw new ItemStatDataLoadException("Invalid value: null");
|
||||
}
|
||||
try {
|
||||
if (value instanceof Map<?, ?> map) {
|
||||
Map<String, Object> resultMap = new HashMap<>();
|
||||
for (Map.Entry<?, ?> entry : map.entrySet()) {
|
||||
if (entry.getKey() instanceof String key) {
|
||||
resultMap.put(key, entry.getValue());
|
||||
} else {
|
||||
throw new ItemStatDataLoadException("Map key is not a String: " + entry.getKey());
|
||||
}
|
||||
}
|
||||
return new MapData(resultMap);
|
||||
} else {
|
||||
throw new ItemStatDataLoadException("Invalid value type for MapData: " + value);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new ItemStatDataLoadException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable MapData getLoadedTag(@NotNull ItemProxy itemProxy) {
|
||||
if (!itemProxy.has(getTagPath(), TagCompound.TYPE_ID)) {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package com.io.yutian.elementoriginlib.item.stat.type;
|
||||
|
||||
import com.io.yutian.elementoriginlib.exception.itemstat.ItemStatDataLoadException;
|
||||
import com.io.yutian.elementoriginlib.item.TagStatItemStackBuilder;
|
||||
import com.io.yutian.elementoriginlib.item.stat.ItemStat;
|
||||
import com.io.yutian.elementoriginlib.item.stat.data.StringListData;
|
||||
|
@ -11,9 +10,7 @@ import org.jetbrains.annotations.NotNull;
|
|||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public abstract class StringListStat extends ItemStat<StringListData> {
|
||||
|
||||
|
@ -29,38 +26,6 @@ public abstract class StringListStat extends ItemStat<StringListData> {
|
|||
itemProxy.editTag(tagCompound1 -> tagCompound1.put(getTagPath(), tagList));
|
||||
}
|
||||
|
||||
@Override
|
||||
public StringListData loadAsObject(@NotNull Object value) throws ItemStatDataLoadException {
|
||||
if (Objects.isNull(value)) {
|
||||
throw new ItemStatDataLoadException("Invalid value: null");
|
||||
}
|
||||
try {
|
||||
if (value instanceof List<?> list) {
|
||||
List<String> stringList = new ArrayList<>();
|
||||
for (Object item : list) {
|
||||
if (item instanceof String str) {
|
||||
stringList.add(str);
|
||||
} else {
|
||||
throw new ItemStatDataLoadException("List contains non-string element: " + item);
|
||||
}
|
||||
}
|
||||
return new StringListData(stringList);
|
||||
} else if (value instanceof String[] array) {
|
||||
// 处理 String[] 类型
|
||||
return new StringListData(Arrays.asList(array));
|
||||
} else if (value instanceof String str) {
|
||||
List<String> stringList = new ArrayList<>();
|
||||
stringList.add(str);
|
||||
return new StringListData(stringList);
|
||||
} else {
|
||||
throw new ItemStatDataLoadException("Invalid value type for StringListData: " + value);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new ItemStatDataLoadException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public StringListData getLoadedTag(@NotNull ItemProxy itemProxy) {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package com.io.yutian.elementoriginlib.item.stat.type;
|
||||
|
||||
import com.io.yutian.elementoriginlib.exception.itemstat.ItemStatDataLoadException;
|
||||
import com.io.yutian.elementoriginlib.item.TagStatItemStackBuilder;
|
||||
import com.io.yutian.elementoriginlib.item.stat.ItemStat;
|
||||
import com.io.yutian.elementoriginlib.item.stat.data.StringData;
|
||||
|
@ -9,8 +8,6 @@ import com.io.yutian.elementoriginlib.tag.TagString;
|
|||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public abstract class StringStat extends ItemStat<StringData> {
|
||||
|
||||
public StringStat(@NotNull String id, @NotNull String path) {
|
||||
|
@ -23,14 +20,6 @@ public abstract class StringStat extends ItemStat<StringData> {
|
|||
itemProxy.editTag(tagCompound1 -> tagCompound1.putString(getTagPath(), statData.getString()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public StringData loadAsObject(@NotNull Object value) {
|
||||
if (Objects.isNull(value)) {
|
||||
throw new ItemStatDataLoadException("Invalid value: null");
|
||||
}
|
||||
return new StringData(value.toString());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public StringData getLoadedTag(@NotNull ItemProxy itemProxy) {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package com.io.yutian.elementoriginlib.item.stat.type;
|
||||
|
||||
import com.io.yutian.elementoriginlib.exception.itemstat.ItemStatDataLoadException;
|
||||
import com.io.yutian.elementoriginlib.item.TagStatItemStackBuilder;
|
||||
import com.io.yutian.elementoriginlib.item.stat.ItemStat;
|
||||
import com.io.yutian.elementoriginlib.item.stat.data.UUIDData;
|
||||
|
@ -9,7 +8,6 @@ import com.io.yutian.elementoriginlib.tag.TagString;
|
|||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
public abstract class UUIDStat extends ItemStat<UUIDData> {
|
||||
|
@ -24,28 +22,6 @@ public abstract class UUIDStat extends ItemStat<UUIDData> {
|
|||
itemProxy.editTag(tagCompound1 -> tagCompound1.putString(getTagPath(), statData.getUUID().toString()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUIDData loadAsObject(@NotNull Object value) throws ItemStatDataLoadException {
|
||||
if (Objects.isNull(value)) {
|
||||
throw new ItemStatDataLoadException("Invalid value: null");
|
||||
}
|
||||
try {
|
||||
if (value instanceof UUID uuid) {
|
||||
return new UUIDData(uuid);
|
||||
} else if (value instanceof String str) {
|
||||
try {
|
||||
return new UUIDData(UUID.fromString(str));
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new ItemStatDataLoadException("Invalid UUID string: " + str, e);
|
||||
}
|
||||
} else {
|
||||
throw new ItemStatDataLoadException("Invalid UUID value: " + value);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new ItemStatDataLoadException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public UUIDData getLoadedTag(@NotNull ItemProxy itemProxy) {
|
||||
|
|
|
@ -15,10 +15,12 @@ public class Lang {
|
|||
private static Map<String, String> langMap = new HashMap<>();
|
||||
|
||||
public static String get(String key) {
|
||||
key = key.toLowerCase();
|
||||
return langMap.getOrDefault(key, "§o"+key);
|
||||
}
|
||||
|
||||
public static String get(String key, Object... args) {
|
||||
key = key.toLowerCase();
|
||||
String s = langMap.getOrDefault(key, "§o"+key);
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
s = s.replace("$"+i, String.valueOf(args[i]));
|
||||
|
@ -27,6 +29,7 @@ public class Lang {
|
|||
}
|
||||
|
||||
public static Optional<String> getOptional(String key) {
|
||||
key = key.toLowerCase();
|
||||
return Optional.ofNullable(langMap.get(key));
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
package com.io.yutian.elementoriginlib.mongodb;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.TYPE})
|
||||
public @interface Collection {
|
||||
|
||||
String value() default "";
|
||||
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package com.io.yutian.elementoriginlib.mongodb;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public interface MongoEntity {
|
||||
|
||||
UUID getUUID();
|
||||
|
||||
}
|
|
@ -0,0 +1,722 @@
|
|||
package com.io.yutian.elementoriginlib.mongodb;
|
||||
|
||||
import com.io.yutian.elementoriginlib.serialize.SerializeHelper;
|
||||
import com.mongodb.BasicDBObject;
|
||||
import com.mongodb.ConnectionString;
|
||||
import com.mongodb.MongoClientSettings;
|
||||
import com.mongodb.client.*;
|
||||
import com.mongodb.client.model.Filters;
|
||||
import com.mongodb.client.result.DeleteResult;
|
||||
import com.mongodb.client.result.UpdateResult;
|
||||
import org.bson.Document;
|
||||
import org.bson.UuidRepresentation;
|
||||
import org.bson.codecs.UuidCodec;
|
||||
import org.bson.codecs.configuration.CodecRegistries;
|
||||
import org.bson.codecs.configuration.CodecRegistry;
|
||||
import org.bson.conversions.Bson;
|
||||
import org.bson.types.ObjectId;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class MongoSupport {
|
||||
private final static Logger LOG = LoggerFactory.getLogger(MongoSupport.class);
|
||||
public final static String ID = "_id";
|
||||
private final static Map<Class<?>, String> classCollectionName = new ConcurrentHashMap<>();
|
||||
private final static Map<String, MongoCollection<Document>> collections = new ConcurrentHashMap<>();
|
||||
|
||||
private static final CodecRegistry CODEC_REGISTRY = CodecRegistries.fromRegistries(
|
||||
CodecRegistries.fromCodecs(new UuidCodec(UuidRepresentation.STANDARD)),
|
||||
MongoClientSettings.getDefaultCodecRegistry()
|
||||
);
|
||||
|
||||
protected MongoDatabase mongoDatabase;
|
||||
|
||||
public MongoSupport(String host, int port, String username, String password, String dbname) {
|
||||
String connectionString = String.format(
|
||||
"mongodb://%s:%s@%s:%d/?authSource=admin",
|
||||
URLEncoder.encode(username, StandardCharsets.UTF_8),
|
||||
URLEncoder.encode(password, StandardCharsets.UTF_8),
|
||||
host, port
|
||||
);
|
||||
MongoClientSettings settings = MongoClientSettings.builder()
|
||||
.applyConnectionString(new ConnectionString(connectionString))
|
||||
.codecRegistry(CODEC_REGISTRY)
|
||||
.uuidRepresentation(UuidRepresentation.STANDARD)
|
||||
.build();
|
||||
MongoClient client = MongoClients.create(settings);
|
||||
mongoDatabase = client.getDatabase(dbname);
|
||||
if (mongoDatabase == null) {
|
||||
throw new IllegalArgumentException("获取数据库实例失败:" + dbname);
|
||||
}
|
||||
}
|
||||
|
||||
public MongoSupport(MongoClient mongo, String dbname) {
|
||||
mongoDatabase = mongo.getDatabase(dbname);
|
||||
if (mongoDatabase == null) {
|
||||
throw new IllegalArgumentException("获取数据库实例失败:" + dbname);
|
||||
}
|
||||
}
|
||||
|
||||
public MongoDatabase getMongoDatabase() {
|
||||
return mongoDatabase;
|
||||
}
|
||||
|
||||
public List<String> getCollectionNames() {
|
||||
List<String> list = new ArrayList<>();
|
||||
MongoCursor<String> cursor = mongoDatabase.listCollectionNames().iterator();
|
||||
while (cursor.hasNext()) {
|
||||
list.add(cursor.next());
|
||||
}
|
||||
cursor.close();
|
||||
return list;
|
||||
}
|
||||
|
||||
public MongoCollection<Document> getCollection(String collectionName) {
|
||||
MongoCollection<Document> coll = collections.get(collectionName);
|
||||
if (coll == null) {
|
||||
coll = mongoDatabase.getCollection(collectionName);
|
||||
collections.put(collectionName, coll);
|
||||
}
|
||||
return coll;
|
||||
}
|
||||
|
||||
public List<Document> findAll(String collectionName) {
|
||||
return find(collectionName, null, null, 0, 0);
|
||||
}
|
||||
|
||||
public List<Document> findAll(String collectionName, Bson orderBy) {
|
||||
return find(collectionName, null, orderBy, 0, 0);
|
||||
}
|
||||
|
||||
public List<Document> findAll(String collectionName, Bson orderBy, int limit) {
|
||||
return find(collectionName, null, orderBy, limit, 0);
|
||||
}
|
||||
|
||||
public List<Document> findAll(String collectionName, int limit) {
|
||||
return find(collectionName, null, null, limit, 0);
|
||||
}
|
||||
|
||||
public List<Document> findAll(String collectionName, int limit, int skip) {
|
||||
return find(collectionName, null, null, limit, skip);
|
||||
}
|
||||
|
||||
public List<Document> findAll(String collectionName, Bson orderBy, int limit, int skip) {
|
||||
return find(collectionName, null, orderBy, limit, skip);
|
||||
}
|
||||
|
||||
private <T> String getCollectionName(Class<T> clazz) {
|
||||
if (classCollectionName.containsKey(clazz)) {
|
||||
return classCollectionName.get(clazz);
|
||||
}
|
||||
String collectionName = clazz.getSimpleName();
|
||||
Collection collection = clazz.getAnnotation(Collection.class);
|
||||
if (collection != null && collection.value() != null && !collection.value().isEmpty()) {
|
||||
collectionName = collection.value();
|
||||
}
|
||||
return classCollectionName.put(clazz, collectionName);
|
||||
}
|
||||
|
||||
public <T> List<T> findAll(Class<T> clazz) {
|
||||
String collectionName = getCollectionName(clazz);
|
||||
return find(clazz, collectionName, null, null, 0, 0);
|
||||
}
|
||||
|
||||
public <T> List<T> findAll(Class<T> clazz, String collectionName) {
|
||||
return find(clazz, collectionName, null, null, 0, 0);
|
||||
}
|
||||
|
||||
public <T> List<T> findAll(Class<T> clazz, String collectionName, Bson orderBy) {
|
||||
return find(clazz, collectionName, null, orderBy, 0, 0);
|
||||
}
|
||||
|
||||
public <T> List<T> findAll(Class<T> clazz, String collectionName, Bson orderBy, int limit) {
|
||||
return find(clazz, collectionName, null, orderBy, limit, 0);
|
||||
}
|
||||
|
||||
public <T> List<T> findAll(Class<T> clazz, String collectionName, int limit) {
|
||||
return find(clazz, collectionName, null, null, limit, 0);
|
||||
}
|
||||
|
||||
public <T> List<T> findAll(Class<T> clazz, String collectionName, int limit, int skip) {
|
||||
return find(clazz, collectionName, null, null, limit, skip);
|
||||
}
|
||||
|
||||
public <T> List<T> findAll(Class<T> clazz, String collectionName, Bson orderBy, int limit, int skip) {
|
||||
return find(clazz, collectionName, null, orderBy, limit, skip);
|
||||
}
|
||||
|
||||
public List<Document> find(String collectionName, Bson filter) {
|
||||
return find(collectionName, filter, null, 0, 0);
|
||||
}
|
||||
|
||||
public List<Document> find(String collectionName, Bson filter, Bson orderBy) {
|
||||
return find(collectionName, filter, orderBy, 0, 0);
|
||||
}
|
||||
|
||||
public List<Document> find(String collectionName, Bson filter, Bson orderBy, int limit) {
|
||||
return find(collectionName, filter, orderBy, 0, 0);
|
||||
}
|
||||
|
||||
public List<Document> find(String collectionName, Bson filter, int limit) {
|
||||
return find(collectionName, filter, null, 0, 0);
|
||||
}
|
||||
|
||||
public List<Document> find(String collectionName, Bson filter, int limit, int skip) {
|
||||
return find(collectionName, filter, null, 0, 0);
|
||||
}
|
||||
|
||||
public List<Document> find(String collectionName, Bson filter, Bson orderBy, int limit, int skip) {
|
||||
FindIterable<Document> find = null;
|
||||
if (filter == null) {
|
||||
find = getCollection(collectionName).find();
|
||||
} else {
|
||||
find = getCollection(collectionName).find(filter);
|
||||
}
|
||||
if (orderBy != null) {
|
||||
find.sort(orderBy);
|
||||
}
|
||||
if (skip > 0) {
|
||||
find.skip(skip);
|
||||
}
|
||||
if (limit > 0) {
|
||||
find.limit(limit);
|
||||
}
|
||||
MongoCursor<Document> cursor = find.iterator();
|
||||
List<Document> list = new ArrayList<>();
|
||||
try {
|
||||
while (cursor.hasNext()) {
|
||||
list.add(cursor.next());
|
||||
}
|
||||
} finally {
|
||||
cursor.close();
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public <T> List<T> find(Class<T> clazz, Bson filter) {
|
||||
String collectionName = getCollectionName(clazz);
|
||||
return find(clazz, collectionName, filter, null, 0, 0);
|
||||
}
|
||||
|
||||
public <T> List<T> find(Class<T> clazz, Bson filter, Bson orderBy) {
|
||||
String collectionName = getCollectionName(clazz);
|
||||
return find(clazz, collectionName, filter, orderBy, 0, 0);
|
||||
}
|
||||
|
||||
public <T> List<T> find(Class<T> clazz, Bson filter, Bson orderBy, int limit) {
|
||||
String collectionName = getCollectionName(clazz);
|
||||
return find(clazz, collectionName, filter, orderBy, limit, 0);
|
||||
}
|
||||
|
||||
public <T> List<T> find(Class<T> clazz, Bson filter, int limit) {
|
||||
String collectionName = getCollectionName(clazz);
|
||||
return find(clazz, collectionName, filter, null, limit, 0);
|
||||
}
|
||||
|
||||
public <T> List<T> find(Class<T> clazz, Bson filter, int limit, int skip) {
|
||||
String collectionName = getCollectionName(clazz);
|
||||
return find(clazz, collectionName, filter, null, limit, skip);
|
||||
}
|
||||
|
||||
public <T> List<T> find(Class<T> clazz, String collectionName, Bson filter) {
|
||||
return find(clazz, collectionName, filter, null, 0, 0);
|
||||
}
|
||||
|
||||
public <T> List<T> find(Class<T> clazz, String collectionName, Bson filter, Bson orderBy) {
|
||||
return find(clazz, collectionName, filter, orderBy, 0, 0);
|
||||
}
|
||||
|
||||
public <T> List<T> find(Class<T> clazz, String collectionName, Bson filter, Bson orderBy, int limit) {
|
||||
return find(clazz, collectionName, filter, orderBy, limit, 0);
|
||||
}
|
||||
|
||||
public <T> List<T> find(Class<T> clazz, String collectionName, Bson filter, int limit) {
|
||||
return find(clazz, collectionName, filter, null, limit, 0);
|
||||
}
|
||||
|
||||
public <T> List<T> find(Class<T> clazz, String collectionName, Bson filter, int limit, int skip) {
|
||||
return find(clazz, collectionName, filter, null, limit, skip);
|
||||
}
|
||||
|
||||
public <T> List<T> find(Class<T> clazz, String collectionName, Bson filter, Bson orderBy, int limit, int skip) {
|
||||
FindIterable<Document> find = null;
|
||||
if (filter == null) {
|
||||
find = getCollection(collectionName).find();
|
||||
} else {
|
||||
find = getCollection(collectionName).find(filter);
|
||||
}
|
||||
if (orderBy != null) {
|
||||
find.sort(orderBy);
|
||||
}
|
||||
if (skip > 0) {
|
||||
find.skip(skip);
|
||||
}
|
||||
if (limit > 0) {
|
||||
find.limit(limit);
|
||||
}
|
||||
MongoCursor<Document> cursor = find.iterator();
|
||||
List<T> list = new ArrayList<T>();
|
||||
try {
|
||||
while (cursor.hasNext()) {
|
||||
Document doc = cursor.next();
|
||||
ObjectId id = doc.getObjectId(ID);
|
||||
if (id != null) {
|
||||
doc.put(ID, id.toHexString());
|
||||
}
|
||||
String json = doc.toJson();
|
||||
list.add(SerializeHelper.deserialize(json, clazz));
|
||||
}
|
||||
} finally {
|
||||
cursor.close();
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public List<Document> distinct(String collectionName, String fieldName, Bson filter) {
|
||||
DistinctIterable<Document> find = null;
|
||||
if (filter == null) {
|
||||
find = getCollection(collectionName).distinct(fieldName, Document.class);
|
||||
} else {
|
||||
find = getCollection(collectionName).distinct(fieldName, filter, Document.class);
|
||||
}
|
||||
MongoCursor<Document> cursor = find.iterator();
|
||||
List<Document> list = new ArrayList<>();
|
||||
try {
|
||||
while (cursor.hasNext()) {
|
||||
list.add(cursor.next());
|
||||
}
|
||||
} finally {
|
||||
cursor.close();
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public Document findOne(String collectionName, Bson filter) {
|
||||
MongoCursor<Document> cursor = getCollection(collectionName).find(filter).iterator();
|
||||
try {
|
||||
if (cursor.hasNext()) {
|
||||
return cursor.next();
|
||||
}
|
||||
} finally {
|
||||
cursor.close();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public <T> T findOne(Class<T> clazz, Bson filter) {
|
||||
String collectionName = getCollectionName(clazz);
|
||||
return findOne(clazz, collectionName, filter);
|
||||
}
|
||||
|
||||
public <T> T findOne(Class<T> clazz, String collectionName, Bson filter) {
|
||||
MongoCursor<Document> cursor = getCollection(collectionName).find(filter).iterator();
|
||||
try {
|
||||
if (cursor.hasNext()) {
|
||||
Document doc = cursor.next();
|
||||
ObjectId id = doc.getObjectId(ID);
|
||||
if (id != null) {
|
||||
doc.put(ID, id.toHexString());
|
||||
}
|
||||
String json = doc.toJson();
|
||||
return SerializeHelper.deserialize(json, clazz);
|
||||
}
|
||||
} finally {
|
||||
cursor.close();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public <T> T findById(Class<T> clazz, UUID id) {
|
||||
String collectionName = getCollectionName(clazz);
|
||||
return findById(clazz, collectionName, id);
|
||||
}
|
||||
|
||||
public <T> T findById(Class<T> clazz, String collectionName, UUID id) {
|
||||
Bson filter = Filters.eq(ID, id);
|
||||
MongoCursor<Document> cursor = getCollection(collectionName).find(filter).iterator();
|
||||
try {
|
||||
if (cursor.hasNext()) {
|
||||
Document doc = cursor.next();
|
||||
ObjectId _id = doc.getObjectId(ID);
|
||||
if (_id != null) {
|
||||
doc.put(ID, _id.toHexString());
|
||||
}
|
||||
String json = doc.toJson();
|
||||
return SerializeHelper.deserialize(json, clazz);
|
||||
}
|
||||
} finally {
|
||||
cursor.close();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Document findById(String collectionName, UUID id) {
|
||||
Bson filter = Filters.eq(ID, id);
|
||||
MongoCursor<Document> cursor = getCollection(collectionName).find(filter).iterator();
|
||||
try {
|
||||
if (cursor.hasNext()) {
|
||||
return cursor.next();
|
||||
}
|
||||
} finally {
|
||||
cursor.close();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public <T> long count(Class<T> clazz) {
|
||||
String collectionName = getCollectionName(clazz);
|
||||
return count(collectionName);
|
||||
}
|
||||
|
||||
public long count(String collectionName) {
|
||||
return getCollection(collectionName).countDocuments();
|
||||
}
|
||||
|
||||
public <T> long count(Class<T> clazz, Bson filter) {
|
||||
String collectionName = getCollectionName(clazz);
|
||||
return count(collectionName, filter);
|
||||
}
|
||||
|
||||
public long count(String collectionName, Bson filter) {
|
||||
if (filter == null) {
|
||||
return getCollection(collectionName).countDocuments();
|
||||
}
|
||||
return getCollection(collectionName).countDocuments(filter);
|
||||
}
|
||||
|
||||
public List<Document> count(String collectionName, String[] groupBy) {
|
||||
return count(collectionName, groupBy, null, 0);
|
||||
}
|
||||
|
||||
public List<Document> count(String collectionName, String[] groupBy, Bson filter) {
|
||||
return count(collectionName, groupBy, filter, 0);
|
||||
}
|
||||
|
||||
public List<Document> count(String collectionName, String[] groupBy, Bson filter, int limit) {
|
||||
StringBuilder mapFunction = new StringBuilder("function(){emit(");
|
||||
int len = groupBy.length;
|
||||
if (len == 1) {
|
||||
mapFunction.append("this.").append(groupBy[0]);
|
||||
} else {
|
||||
mapFunction.append("{");
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (i > 0) {
|
||||
mapFunction.append(",");
|
||||
}
|
||||
mapFunction.append(groupBy[i]).append(":this.").append(groupBy[i]);
|
||||
}
|
||||
mapFunction.append("}");
|
||||
}
|
||||
mapFunction.append(",1");
|
||||
mapFunction.append(");}");
|
||||
StringBuilder reduceFunction = new StringBuilder("function(key, values){");
|
||||
reduceFunction.append("var total = 0;");
|
||||
reduceFunction.append("values.forEach(function(val){total += val;});");
|
||||
reduceFunction.append("return total;");
|
||||
reduceFunction.append("}");
|
||||
MapReduceIterable<Document> find = getCollection(collectionName).mapReduce(mapFunction.toString(), reduceFunction.toString());
|
||||
if (filter != null) {
|
||||
find.filter(filter);
|
||||
}
|
||||
if (limit > 0) {
|
||||
find.limit(limit);
|
||||
}
|
||||
find.jsMode(true);
|
||||
MongoCursor<Document> cursor = find.iterator();
|
||||
List<Document> list = new ArrayList<Document>();
|
||||
try {
|
||||
while (cursor.hasNext()) {
|
||||
Document doc = cursor.next();
|
||||
if (len == 1) {
|
||||
doc.put(groupBy[0], doc.get("_id"));
|
||||
} else {
|
||||
doc.putAll((Document) doc.get("_id"));
|
||||
}
|
||||
doc.remove("_id");
|
||||
|
||||
Object val = doc.get("value");
|
||||
if (val instanceof List) {
|
||||
val = ((List) val).get(0);
|
||||
}
|
||||
long count = 0;
|
||||
if (val instanceof Number) {
|
||||
count = ((Number)val).longValue();
|
||||
} else {
|
||||
LOG.warn("{} is not a number!!! doc={}", val, doc);
|
||||
}
|
||||
doc.remove("value");
|
||||
doc.put("count", count);
|
||||
list.add(doc);
|
||||
}
|
||||
} finally {
|
||||
cursor.close();
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public List<Document> mapReduce(String collectionName, String mapFunction, String reduceFunction) {
|
||||
return mapReduce(collectionName, mapFunction, reduceFunction, null, null, null, 0);
|
||||
}
|
||||
|
||||
public List<Document> mapReduce(String collectionName, String mapFunction, String reduceFunction, Bson filter) {
|
||||
return mapReduce(collectionName, mapFunction, reduceFunction, null, filter, null, 0);
|
||||
}
|
||||
|
||||
public List<Document> mapReduce(String collectionName, String mapFunction, String reduceFunction, Bson filter, Bson orderBy) {
|
||||
return mapReduce(collectionName, mapFunction, reduceFunction, null, filter, orderBy, 0);
|
||||
}
|
||||
|
||||
public List<Document> mapReduce(String collectionName, String mapFunction, String reduceFunction, Bson filter, int limit) {
|
||||
return mapReduce(collectionName, mapFunction, reduceFunction, null, filter, null, limit);
|
||||
}
|
||||
|
||||
public List<Document> mapReduce(String collectionName, String mapFunction, String reduceFunction, String finalizeFunction) {
|
||||
return mapReduce(collectionName, mapFunction, reduceFunction, finalizeFunction, null, null, 0);
|
||||
}
|
||||
|
||||
public List<Document> mapReduce(String collectionName, String mapFunction, String reduceFunction, String finalizeFunction, Bson filter) {
|
||||
return mapReduce(collectionName, mapFunction, reduceFunction, finalizeFunction, filter, null, 0);
|
||||
}
|
||||
|
||||
public List<Document> mapReduce(String collectionName, String mapFunction, String reduceFunction, String finalizeFunction, Bson filter, Bson orderBy) {
|
||||
return mapReduce(collectionName, mapFunction, reduceFunction, finalizeFunction, filter, orderBy, 0);
|
||||
}
|
||||
|
||||
public List<Document> mapReduce(String collectionName, String mapFunction, String reduceFunction, String finalizeFunction, Bson filter, int limit) {
|
||||
return mapReduce(Document.class, collectionName, mapFunction, reduceFunction, finalizeFunction, filter, null, limit);
|
||||
}
|
||||
|
||||
public List<Document> mapReduce(String collectionName, String mapFunction, String reduceFunction, String finalizeFunction, Bson filter, Bson orderBy, int
|
||||
limit) {
|
||||
return mapReduce(Document.class, collectionName, mapFunction, reduceFunction, finalizeFunction, filter, orderBy, limit);
|
||||
}
|
||||
|
||||
public <T> List<T> mapReduce(Class<T> resultClass, String collectionName, String mapFunction, String reduceFunction, String finalizeFunction, Bson
|
||||
filter, int limit) {
|
||||
return mapReduce(resultClass, collectionName, mapFunction, reduceFunction, finalizeFunction, filter, null, limit);
|
||||
}
|
||||
|
||||
public <T> List<T> mapReduce(Class<T> resultClass, String collectionName, String mapFunction, String reduceFunction, String finalizeFunction, Bson
|
||||
filter, Bson orderBy, int limit) {
|
||||
MapReduceIterable<T> find = getCollection(collectionName).mapReduce(mapFunction, reduceFunction, resultClass);
|
||||
if (filter != null) {
|
||||
find.filter(filter);
|
||||
}
|
||||
if (finalizeFunction != null && !finalizeFunction.isEmpty()) {
|
||||
find.finalizeFunction(finalizeFunction);
|
||||
}
|
||||
if (orderBy != null) {
|
||||
find.sort(orderBy);
|
||||
}
|
||||
if (limit > 0) {
|
||||
find.limit(limit);
|
||||
}
|
||||
find.jsMode(true);
|
||||
MongoCursor<T> cursor = find.iterator();
|
||||
List<T> list = new ArrayList<T>();
|
||||
try {
|
||||
while (cursor.hasNext()) {
|
||||
list.add(cursor.next());
|
||||
}
|
||||
} finally {
|
||||
cursor.close();
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public void save(Object entity) {
|
||||
Class<?> clazz = entity.getClass();
|
||||
String collectionName = getCollectionName(clazz);
|
||||
save(entity, collectionName);
|
||||
}
|
||||
|
||||
public void save(Object entity, String collectionName) {
|
||||
if (entity instanceof Document) {
|
||||
getCollection(collectionName).insertOne((Document) entity);
|
||||
} else if (entity instanceof Map) {
|
||||
getCollection(collectionName).insertOne(new Document((Map<String, Object>) entity));
|
||||
} else {
|
||||
String json = toJson(entity);
|
||||
getCollection(collectionName).insertOne(Document.parse(json));
|
||||
}
|
||||
}
|
||||
|
||||
public void saveAll(List<?> list) {
|
||||
Class<?> clazz = list.get(0).getClass();
|
||||
String collectionName = getCollectionName(clazz);
|
||||
saveAll(list, collectionName);
|
||||
}
|
||||
|
||||
public void saveAll(List<?> list, String collectionName) {
|
||||
List<Document> docList = new ArrayList<>();
|
||||
for (Object obj : list) {
|
||||
if (obj instanceof Document) {
|
||||
docList.add((Document) obj);
|
||||
} else if (obj instanceof Map) {
|
||||
docList.add(new Document((Map<String, Object>) obj));
|
||||
} else {
|
||||
String json = toJson(obj);
|
||||
docList.add(Document.parse(json));
|
||||
}
|
||||
}
|
||||
getCollection(collectionName).insertMany(docList);
|
||||
}
|
||||
|
||||
public <T> boolean update(T entity) {
|
||||
String collectionName = getCollectionName(entity.getClass());
|
||||
return update(entity, collectionName);
|
||||
}
|
||||
|
||||
public <T> boolean update(T entity, String collectionName) {
|
||||
UUID id = null;
|
||||
if (entity instanceof MongoEntity mongoEntity) {
|
||||
|
||||
}
|
||||
return updateById(entity, collectionName, id);
|
||||
}
|
||||
|
||||
|
||||
public <T> long update(T entity, Bson filter) {
|
||||
String collectionName = getCollectionName(entity.getClass());
|
||||
return update(entity, collectionName, filter, false);
|
||||
}
|
||||
|
||||
public <T> long update(T entity, Bson filter, boolean mutil) {
|
||||
String collectionName = getCollectionName(entity.getClass());
|
||||
return update(entity, collectionName, filter, mutil);
|
||||
}
|
||||
|
||||
public <T> long update(T entity, String collectionName, Bson filter, boolean mutil) {
|
||||
String json = toJson(entity);
|
||||
BasicDBObject update = BasicDBObject.parse(json);
|
||||
return update(collectionName, filter, new BasicDBObject("$set", update), mutil);
|
||||
}
|
||||
|
||||
public long update(String collectionName, Bson filter, UpdateEntity updateEntity) {
|
||||
return update(collectionName, filter, updateEntity, false);
|
||||
}
|
||||
|
||||
public long update(String collectionName, Bson filter, UpdateEntity updateEntity, boolean mutil) {
|
||||
BasicDBObject _update = new BasicDBObject();
|
||||
if (!updateEntity.inc().isEmpty()) {
|
||||
_update.append("$inc", updateEntity.inc());
|
||||
}
|
||||
if (!updateEntity.set().isEmpty()) {
|
||||
_update.append("$set", updateEntity.set());
|
||||
}
|
||||
if (!updateEntity.unset().isEmpty()) {
|
||||
_update.append("$unset", updateEntity.unset());
|
||||
}
|
||||
return update(collectionName, filter, _update, mutil);
|
||||
}
|
||||
|
||||
public long update(String collectionName, Bson filter, Bson update, boolean mutil) {
|
||||
UpdateResult result = null;
|
||||
if (mutil) {
|
||||
result = getCollection(collectionName).updateMany(filter, update);
|
||||
} else {
|
||||
result = getCollection(collectionName).updateOne(filter, update);
|
||||
}
|
||||
if (result.wasAcknowledged()) {
|
||||
return result.getModifiedCount();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public <T> boolean updateById(T entity, UUID id) {
|
||||
String collectionName = getCollectionName(entity.getClass());
|
||||
return updateById(entity, collectionName, id);
|
||||
}
|
||||
|
||||
public <T> boolean updateById(T entity, String collectionName, UUID id) {
|
||||
if (id == null) {
|
||||
throw new IllegalArgumentException("id不能为空");
|
||||
}
|
||||
String json = toJson(entity);
|
||||
Bson filter = Filters.eq(ID, id);
|
||||
BasicDBObject update = BasicDBObject.parse(json);
|
||||
UpdateResult result = getCollection(collectionName).updateOne(filter, new BasicDBObject("$set", update));
|
||||
if (result.wasAcknowledged()) {
|
||||
if (result.getModifiedCount() > 0) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean updateById(String collectionName, UpdateEntity updateEntity, UUID id) {
|
||||
BasicDBObject _update = new BasicDBObject();
|
||||
if (!updateEntity.inc().isEmpty()) {
|
||||
_update.append("$inc", updateEntity.inc());
|
||||
}
|
||||
if (!updateEntity.set().isEmpty()) {
|
||||
_update.append("$set", updateEntity.set());
|
||||
}
|
||||
if (!updateEntity.unset().isEmpty()) {
|
||||
_update.append("$unset", updateEntity.unset());
|
||||
}
|
||||
return updateById(collectionName, _update, id);
|
||||
}
|
||||
|
||||
public boolean updateById(String collectionName, Bson update, UUID id) {
|
||||
if (id == null) {
|
||||
throw new IllegalArgumentException("id不能为空");
|
||||
}
|
||||
Bson filter = Filters.eq(ID, id);
|
||||
UpdateResult result = getCollection(collectionName).updateOne(filter, update);
|
||||
if (result.wasAcknowledged()) {
|
||||
return (result.getModifiedCount() > 0);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean deleteOne(String collectionName, Bson filter) {
|
||||
DeleteResult result = getCollection(collectionName).deleteOne(filter);
|
||||
if (result.wasAcknowledged()) {
|
||||
return (result.getDeletedCount() > 0);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public long deleteAll(String collectionName, Bson filter) {
|
||||
DeleteResult result = getCollection(collectionName).deleteMany(filter);
|
||||
if (result.wasAcknowledged()) {
|
||||
return result.getDeletedCount();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public boolean deleteById(String collectionName, UUID id) {
|
||||
return deleteOne(collectionName, Filters.eq(ID, id));
|
||||
}
|
||||
|
||||
public void drop(String collectionName) {
|
||||
getCollection(collectionName).drop();
|
||||
}
|
||||
|
||||
public void createIndex(String collectionName, Bson keys) {
|
||||
getCollection(collectionName).createIndex(keys);
|
||||
}
|
||||
|
||||
public void dropIndexes(String collectionName) {
|
||||
getCollection(collectionName).dropIndexes();
|
||||
}
|
||||
|
||||
public void dropIndex(String collectionName, String indexName) {
|
||||
getCollection(collectionName).dropIndex(indexName);
|
||||
}
|
||||
|
||||
protected String toJson(Object obj) {
|
||||
return SerializeHelper.serialize(obj);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
package com.io.yutian.elementoriginlib.mongodb;
|
||||
|
||||
import com.mongodb.BasicDBObject;
|
||||
|
||||
public class UpdateEntity {
|
||||
private BasicDBObject incObjects = new BasicDBObject();
|
||||
private BasicDBObject setObjects = new BasicDBObject();
|
||||
private BasicDBObject unsetObjects = new BasicDBObject();
|
||||
|
||||
public UpdateEntity() {
|
||||
}
|
||||
|
||||
public UpdateEntity(BasicDBObject set) {
|
||||
this.setObjects = set;
|
||||
}
|
||||
|
||||
public UpdateEntity set(String key, Object value) {
|
||||
setObjects.append(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public UpdateEntity unset(String key) {
|
||||
unsetObjects.append(key, 0);
|
||||
return this;
|
||||
}
|
||||
|
||||
public UpdateEntity inc(String key, int value) {
|
||||
incObjects.append(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BasicDBObject set() {
|
||||
return setObjects;
|
||||
}
|
||||
|
||||
public BasicDBObject unset() {
|
||||
return unsetObjects;
|
||||
}
|
||||
|
||||
public BasicDBObject inc() {
|
||||
return incObjects;
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
setObjects.clear();
|
||||
incObjects.clear();
|
||||
unsetObjects.clear();
|
||||
}
|
||||
}
|
|
@ -4,6 +4,9 @@ import com.fasterxml.jackson.annotation.JsonProperty;
|
|||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.util.NumberConversions;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
|
@ -61,6 +64,23 @@ public class Point {
|
|||
this.z = z;
|
||||
}
|
||||
|
||||
public double distance(@NotNull Point o) {
|
||||
return Math.sqrt(this.distanceSquared(o));
|
||||
}
|
||||
|
||||
public double distance(@NotNull Vector o) {
|
||||
return Math.sqrt(this.distanceSquared(o));
|
||||
}
|
||||
|
||||
public double distanceSquared(@NotNull Point o) {
|
||||
return NumberConversions.square(this.x - o.x) + NumberConversions.square(this.y - o.y) + NumberConversions.square(this.z - o.z);
|
||||
}
|
||||
|
||||
public double distanceSquared(@NotNull Vector o) {
|
||||
return NumberConversions.square(this.x - o.getX()) + NumberConversions.square(this.y - o.getY()) + NumberConversions.square(this.z - o.getZ());
|
||||
}
|
||||
|
||||
|
||||
public Point clone() {
|
||||
return new Point(x, y, z);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package com.io.yutian.elementoriginlib.point;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAutoDetect;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
|
@ -30,6 +29,13 @@ public class Region {
|
|||
return max;
|
||||
}
|
||||
|
||||
public Point getCenter() {
|
||||
double centerX = (min.getX() + max.getX()) / 2.0;
|
||||
double centerY = (min.getY() + max.getY()) / 2.0;
|
||||
double centerZ = (min.getZ() + max.getZ()) / 2.0;
|
||||
return new Point(centerX, centerY, centerZ);
|
||||
}
|
||||
|
||||
public static Region deserialize(ConfigurationSection section) {
|
||||
World world1 = Bukkit.getWorld(section.getString("world"));
|
||||
Point point1 = Point.deserialize(section.getConfigurationSection("min"));
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
package com.io.yutian.elementoriginlib.scanner;
|
||||
|
||||
public interface ClassLoaderProcessor {
|
||||
|
||||
boolean isMatch(Class loaderClass, byte[] classBytes);
|
||||
|
||||
void process(Class loaderClass, Object instance);
|
||||
|
||||
}
|
|
@ -0,0 +1,317 @@
|
|||
package com.io.yutian.elementoriginlib.scanner;
|
||||
|
||||
import com.io.yutian.elementoriginlib.logger.Logger;
|
||||
import com.io.yutian.elementoriginlib.shadowloader.BytecodeRewriter;
|
||||
import com.io.yutian.elementoriginlib.shadowloader.ShadowClassLoader;
|
||||
import javassist.ClassPool;
|
||||
import javassist.CtClass;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
|
||||
public class ClassScanner {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(ClassScanner.class);
|
||||
private static final int THREAD_COUNT = Runtime.getRuntime().availableProcessors();
|
||||
public static final Set<String> DEFAULT_PACKAGES = new HashSet<>(Arrays.asList("com.io.yutian"));
|
||||
public static final Set<String> DEFAULT_EXCLUDE_PACKAGES = new HashSet<>(Arrays.asList("com.io.yutian.elementoriginlib"));
|
||||
|
||||
private Set<String> packageNames;
|
||||
private Set<String> excludePackageNames;
|
||||
|
||||
private ClassLoaderProcessor classLoaderProcessor;
|
||||
private ClassLoader classLoader;
|
||||
|
||||
private Set<Class<?>> scannedClasses = ConcurrentHashMap.newKeySet();
|
||||
private Map<String, Object> scannedClassInstances = new ConcurrentHashMap<>();
|
||||
|
||||
public ClassScanner(Set<String> packageNames, Set<String> excludePackageNames, ClassLoader classLoader, ClassLoaderProcessor classLoaderProcessor) {
|
||||
this.packageNames = packageNames;
|
||||
this.excludePackageNames = excludePackageNames;
|
||||
this.classLoader = classLoader;
|
||||
this.classLoaderProcessor = classLoaderProcessor;
|
||||
}
|
||||
|
||||
public void scan(File pluginsFolder) {
|
||||
File[] jars = pluginsFolder.listFiles((dir, name) -> name.endsWith(".jar"));
|
||||
if (jars == null) return;
|
||||
ExecutorService executor = Executors.newFixedThreadPool(THREAD_COUNT);
|
||||
|
||||
for (File jar : jars) {
|
||||
executor.submit(() -> {
|
||||
try {
|
||||
scanJar(jar);
|
||||
} catch (Exception e) {
|
||||
LOGGER.error(e.getMessage(), e);
|
||||
}
|
||||
});
|
||||
}
|
||||
executor.shutdown();
|
||||
try {
|
||||
executor.awaitTermination(60, TimeUnit.SECONDS);
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
private void scanJar(File jarFile) throws IOException {
|
||||
try (JarFile jar = new JarFile(jarFile)) {
|
||||
Enumeration<JarEntry> entries = jar.entries();
|
||||
URLClassLoader urlClassLoader = new URLClassLoader(new URL[]{jarFile.toURI().toURL()}, classLoader);
|
||||
ShadowClassLoader shadowLoader = new ShadowClassLoader(classLoader);
|
||||
|
||||
while (entries.hasMoreElements()) {
|
||||
JarEntry entry = entries.nextElement();
|
||||
if (entry.getName().endsWith(".class")) {
|
||||
String className = entry.getName().replace("/", ".").replace(".class", "");
|
||||
if (excludePackageNames.stream().anyMatch(className::startsWith)) {
|
||||
continue;
|
||||
}
|
||||
if (packageNames.stream().noneMatch(className::startsWith)) {
|
||||
continue;
|
||||
}
|
||||
try (InputStream is = jar.getInputStream(entry)) {
|
||||
byte[] originalBytes = is.readAllBytes();
|
||||
Class<?> clazz = urlClassLoader.loadClass(className);
|
||||
if (classLoaderProcessor.isMatch(clazz, originalBytes)) {
|
||||
String newName = "lib.shadow." + clazz.getName();
|
||||
byte[] newBytes = BytecodeRewriter.rewriteClass(originalBytes, className, newName);
|
||||
Class<?> newClass = shadowLoader.define(newName, newBytes);
|
||||
Object instance = newClass.newInstance();
|
||||
classLoaderProcessor.process(newClass, instance);
|
||||
scannedClasses.add(clazz);
|
||||
scannedClassInstances.put(clazz.getName(), instance);
|
||||
}
|
||||
} catch (Throwable ignored) {
|
||||
LOGGER.error(ignored.getMessage(), ignored);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static Map<String, Map<String, Object>> getClassAnnotations(byte[] classBytes) {
|
||||
Map<String, Map<String, Object>> annotations = new HashMap<>();
|
||||
try (DataInputStream in = new DataInputStream(new ByteArrayInputStream(classBytes))) {
|
||||
in.skipBytes(8); // magic, minor, major
|
||||
int cpCount = in.readUnsignedShort();
|
||||
|
||||
Map<Integer, String> utf8 = new HashMap<>();
|
||||
Map<Integer, Integer> classInfo = new HashMap<>();
|
||||
|
||||
for (int i = 1; i < cpCount; i++) {
|
||||
int tag = in.readUnsignedByte();
|
||||
switch (tag) {
|
||||
case 1 -> utf8.put(i, in.readUTF());
|
||||
case 3, 4 -> in.skipBytes(4);
|
||||
case 5, 6 -> { in.skipBytes(8); i++; }
|
||||
case 7 -> classInfo.put(i, in.readUnsignedShort());
|
||||
case 8 -> in.readUnsignedShort();
|
||||
case 9, 10, 11, 12, 18 -> in.skipBytes(4);
|
||||
case 15 -> in.skipBytes(3);
|
||||
case 16 -> in.skipBytes(2);
|
||||
case 17 -> in.skipBytes(4);
|
||||
default -> throw new IOException("Bad constant pool tag: " + tag);
|
||||
}
|
||||
}
|
||||
|
||||
in.skipBytes(2 + 2 + 2); // access_flags, this_class, super_class
|
||||
|
||||
int interfacesCount = in.readUnsignedShort();
|
||||
in.skipBytes(2 * interfacesCount);
|
||||
|
||||
int fieldsCount = in.readUnsignedShort();
|
||||
skipAttributes(in, fieldsCount);
|
||||
|
||||
int methodsCount = in.readUnsignedShort();
|
||||
skipAttributes(in, methodsCount);
|
||||
|
||||
int attributesCount = in.readUnsignedShort();
|
||||
for (int i = 0; i < attributesCount; i++) {
|
||||
int nameIndex = in.readUnsignedShort();
|
||||
String attrName = utf8.get(nameIndex);
|
||||
int length = in.readInt();
|
||||
if ("RuntimeVisibleAnnotations".equals(attrName)) {
|
||||
int numAnnotations = in.readUnsignedShort();
|
||||
for (int j = 0; j < numAnnotations; j++) {
|
||||
int typeIndex = in.readUnsignedShort();
|
||||
String desc = utf8.get(typeIndex);
|
||||
if (desc == null) continue;
|
||||
String annotationClass = desc.substring(1, desc.length() - 1).replace("/", ".");
|
||||
Map<String, Object> values = readAnnotationValues(in, utf8);
|
||||
annotations.put(annotationClass, values);
|
||||
}
|
||||
} else {
|
||||
in.skipBytes(length);
|
||||
}
|
||||
}
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
return annotations;
|
||||
}
|
||||
|
||||
private static void skipAttributes(DataInputStream in, int count) throws IOException {
|
||||
for (int i = 0; i < count; i++) {
|
||||
in.skipBytes(6); // access_flags, name_index, descriptor_index
|
||||
int attributesCount = in.readUnsignedShort();
|
||||
for (int j = 0; j < attributesCount; j++) {
|
||||
in.skipBytes(2); // attribute_name_index
|
||||
int length = in.readInt();
|
||||
in.skipBytes(length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Map<String, Object> readAnnotationValues(DataInputStream in, Map<Integer, String> utf8) throws IOException {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
int numPairs = in.readUnsignedShort();
|
||||
for (int i = 0; i < numPairs; i++) {
|
||||
int elementNameIndex = in.readUnsignedShort();
|
||||
String elementName = utf8.get(elementNameIndex);
|
||||
Object value = readElementValue(in, utf8);
|
||||
map.put(elementName, value);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
private static Object readElementValue(DataInputStream in, Map<Integer, String> utf8) throws IOException {
|
||||
char tag = (char) in.readUnsignedByte();
|
||||
return switch (tag) {
|
||||
case 'B', 'C', 'D', 'F', 'I', 'J', 'S', 'Z', 's' -> {
|
||||
int constIndex = in.readUnsignedShort();
|
||||
yield utf8.get(constIndex);
|
||||
}
|
||||
case 'e' -> {
|
||||
in.skipBytes(4);
|
||||
yield "<Enum>";
|
||||
}
|
||||
case 'c' -> {
|
||||
in.skipBytes(2);
|
||||
yield "<Class>";
|
||||
}
|
||||
case '@' -> {
|
||||
skipAnnotation(in, utf8);
|
||||
yield "<Annotation>";
|
||||
}
|
||||
case '[' -> {
|
||||
int numValues = in.readUnsignedShort();
|
||||
List<Object> list = new ArrayList<>();
|
||||
for (int i = 0; i < numValues; i++) {
|
||||
list.add(readElementValue(in, utf8));
|
||||
}
|
||||
yield list;
|
||||
}
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
|
||||
private static void skipAnnotation(DataInputStream in, Map<Integer, String> utf8) throws IOException {
|
||||
in.skipBytes(2);
|
||||
int numPairs = in.readUnsignedShort();
|
||||
for (int i = 0; i < numPairs; i++) {
|
||||
in.skipBytes(2);
|
||||
readElementValue(in, utf8);
|
||||
}
|
||||
}
|
||||
|
||||
public static String getSuperClassName(byte[] classBytes) {
|
||||
try (DataInputStream in = new DataInputStream(new ByteArrayInputStream(classBytes))) {
|
||||
in.skipBytes(8); // magic + minor + major
|
||||
int constantPoolCount = in.readUnsignedShort();
|
||||
|
||||
Map<Integer, String> utf8Constants = new HashMap<>();
|
||||
Map<Integer, Integer> classInfo = new HashMap<>();
|
||||
|
||||
for (int i = 1; i < constantPoolCount; i++) {
|
||||
int tag = in.readUnsignedByte();
|
||||
switch (tag) {
|
||||
case 1 -> utf8Constants.put(i, in.readUTF()); // Utf8
|
||||
case 3, 4 -> in.skipBytes(4);
|
||||
case 5, 6 -> { in.skipBytes(8); i++; }
|
||||
case 7 -> classInfo.put(i, in.readUnsignedShort());
|
||||
case 8 -> in.readUnsignedShort();
|
||||
case 9, 10, 11, 12, 18 -> in.skipBytes(4);
|
||||
case 15 -> in.skipBytes(3);
|
||||
case 16 -> in.skipBytes(2);
|
||||
case 17 -> in.skipBytes(4);
|
||||
default -> throw new IOException("Bad constant pool tag: " + tag);
|
||||
}
|
||||
}
|
||||
|
||||
in.skipBytes(2); // access_flags
|
||||
in.skipBytes(2); // this_class
|
||||
int superClassIndex = in.readUnsignedShort();
|
||||
|
||||
Integer nameIndex = classInfo.get(superClassIndex);
|
||||
if (nameIndex != null) {
|
||||
return utf8Constants.get(nameIndex).replace("/", ".");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Set<String> getInterfaceNames(byte[] classBytes) {
|
||||
Set<String> interfaces = new HashSet<>();
|
||||
try (DataInputStream in = new DataInputStream(new ByteArrayInputStream(classBytes))) {
|
||||
in.skipBytes(8); // magic + minor + major
|
||||
int constantPoolCount = in.readUnsignedShort();
|
||||
|
||||
Map<Integer, String> utf8Constants = new HashMap<>();
|
||||
Map<Integer, Integer> classInfo = new HashMap<>();
|
||||
|
||||
for (int i = 1; i < constantPoolCount; i++) {
|
||||
int tag = in.readUnsignedByte();
|
||||
switch (tag) {
|
||||
case 1 -> utf8Constants.put(i, in.readUTF()); // Utf8
|
||||
case 3, 4 -> in.skipBytes(4); // int, float
|
||||
case 5, 6 -> { in.skipBytes(8); i++; } // long, double
|
||||
case 7 -> classInfo.put(i, in.readUnsignedShort()); // Class -> name_index
|
||||
case 8 -> in.readUnsignedShort(); // String
|
||||
case 9, 10, 11, 12, 18 -> in.skipBytes(4); // Field/Method/InterfaceMethod/NameAndType/InvokeDynamic
|
||||
case 15 -> in.skipBytes(3); // MethodHandle
|
||||
case 16 -> in.skipBytes(2); // MethodType
|
||||
case 17 -> in.skipBytes(4); // Dynamic
|
||||
default -> throw new IOException("Bad constant pool tag: " + tag);
|
||||
}
|
||||
}
|
||||
|
||||
in.skipBytes(2); // access flags
|
||||
in.skipBytes(2); // this class
|
||||
in.skipBytes(2); // super class
|
||||
|
||||
int interfacesCount = in.readUnsignedShort();
|
||||
for (int i = 0; i < interfacesCount; i++) {
|
||||
int index = in.readUnsignedShort();
|
||||
Integer nameIndex = classInfo.get(index);
|
||||
if (nameIndex != null) {
|
||||
String iface = utf8Constants.get(nameIndex);
|
||||
if (iface != null) {
|
||||
interfaces.add(iface.replace("/", "."));
|
||||
}
|
||||
}
|
||||
}
|
||||
return interfaces;
|
||||
} catch (IOException e) {
|
||||
return interfaces;
|
||||
}
|
||||
}
|
||||
|
||||
public Set<Class<?>> getScannedClasses() {
|
||||
return Collections.unmodifiableSet(scannedClasses);
|
||||
}
|
||||
|
||||
public Map<String, Object> getScannedClassInstances() {
|
||||
return Collections.unmodifiableMap(scannedClassInstances);
|
||||
}
|
||||
|
||||
}
|
|
@ -11,7 +11,6 @@ import com.io.yutian.elementoriginlib.logger.Logger;
|
|||
import com.io.yutian.elementoriginlib.serialize.serializers.*;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
public class SerializeHelper {
|
||||
|
@ -26,11 +25,11 @@ public class SerializeHelper {
|
|||
objectMapper = new ObjectMapper();
|
||||
objectMapper.setVisibility(
|
||||
VisibilityChecker.Std.defaultInstance()
|
||||
.withFieldVisibility(JsonAutoDetect.Visibility.ANY)
|
||||
.withFieldVisibility(JsonAutoDetect.Visibility.NONE)
|
||||
.withGetterVisibility(JsonAutoDetect.Visibility.NONE)
|
||||
.withSetterVisibility(JsonAutoDetect.Visibility.NONE)
|
||||
.withIsGetterVisibility(JsonAutoDetect.Visibility.NONE)
|
||||
.withCreatorVisibility(JsonAutoDetect.Visibility.NONE)
|
||||
.withCreatorVisibility(JsonAutoDetect.Visibility.ANY)
|
||||
);
|
||||
|
||||
objectMapper.registerModule(new AfterburnerModule());
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
package com.io.yutian.elementoriginlib.shadowloader;
|
||||
|
||||
import javassist.ClassPool;
|
||||
import javassist.CtClass;
|
||||
|
||||
public class BytecodeRewriter {
|
||||
|
||||
public static byte[] rewriteClass(byte[] originalBytes, String originalName, String newName) throws Exception {
|
||||
ClassPool pool = ClassPool.getDefault();
|
||||
CtClass ct = pool.makeClass(new java.io.ByteArrayInputStream(originalBytes));
|
||||
ct.setName(newName);
|
||||
byte[] result = ct.toBytecode();
|
||||
ct.detach();
|
||||
return result;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package com.io.yutian.elementoriginlib.shadowloader;
|
||||
|
||||
public class ShadowClassLoader extends ClassLoader {
|
||||
|
||||
public ShadowClassLoader(ClassLoader parent) {
|
||||
super(parent);
|
||||
}
|
||||
|
||||
public Class<?> define(String name, byte[] bytecode) {
|
||||
return defineClass(name, bytecode, 0, bytecode.length);
|
||||
}
|
||||
}
|
|
@ -33,6 +33,13 @@ public class ClassUtil {
|
|||
return false;
|
||||
}
|
||||
|
||||
public static Class<?> getWrapperType(Class<?> clazz) {
|
||||
if (clazz == null) {
|
||||
return null;
|
||||
}
|
||||
return PRIMITIVE_TO_WRAPPER.getOrDefault(clazz, clazz);
|
||||
}
|
||||
|
||||
public static String getJar(Plugin plugin) {
|
||||
String p = plugin.getClass().getProtectionDomain().getCodeSource().getLocation().getPath();
|
||||
return p.substring(1);
|
||||
|
|
314
src/main/java/com/io/yutian/elementoriginlib/util/ColorUtil.java
Normal file
314
src/main/java/com/io/yutian/elementoriginlib/util/ColorUtil.java
Normal file
|
@ -0,0 +1,314 @@
|
|||
package com.io.yutian.elementoriginlib.util;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
import java.awt.*;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.regex.Matcher;
|
||||
|
||||
public class ColorUtil {
|
||||
|
||||
public static final List<String> SPECIAL_COLORS = Arrays.asList("&l", "&n", "&o", "&k", "&m");
|
||||
|
||||
private static final Map<Color, ChatColor> COLORS = ImmutableMap.<Color, ChatColor>builder()
|
||||
.put(new Color(0), ChatColor.getByChar('0'))
|
||||
.put(new Color(170), ChatColor.getByChar('1'))
|
||||
.put(new Color(43520), ChatColor.getByChar('2'))
|
||||
.put(new Color(43690), ChatColor.getByChar('3'))
|
||||
.put(new Color(11141120), ChatColor.getByChar('4'))
|
||||
.put(new Color(11141290), ChatColor.getByChar('5'))
|
||||
.put(new Color(16755200), ChatColor.getByChar('6'))
|
||||
.put(new Color(11184810), ChatColor.getByChar('7'))
|
||||
.put(new Color(5592405), ChatColor.getByChar('8'))
|
||||
.put(new Color(5592575), ChatColor.getByChar('9'))
|
||||
.put(new Color(5635925), ChatColor.getByChar('a'))
|
||||
.put(new Color(5636095), ChatColor.getByChar('b'))
|
||||
.put(new Color(16733525), ChatColor.getByChar('c'))
|
||||
.put(new Color(16733695), ChatColor.getByChar('d'))
|
||||
.put(new Color(16777045), ChatColor.getByChar('e'))
|
||||
.put(new Color(16777215), ChatColor.getByChar('f'))
|
||||
.build();
|
||||
|
||||
private static final List<Pattern> PATTERNS = Arrays.asList(new GradientPattern(), new SolidPattern(), new RainbowPattern());
|
||||
|
||||
private static final LruCache LRU_CACHE = new LruCache(512);
|
||||
|
||||
@Nonnull
|
||||
public static String process(@Nonnull String string) {
|
||||
String result = LRU_CACHE.getResult(string);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
String input = string;
|
||||
for (Pattern pattern : PATTERNS) {
|
||||
string = pattern.process(string);
|
||||
}
|
||||
string = ChatColor.translateAlternateColorCodes('&', string);
|
||||
LRU_CACHE.put(input, string);
|
||||
return string;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static List<String> process(@Nonnull List<String> strings) {
|
||||
strings.replaceAll(ColorUtil::process);
|
||||
return strings;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static String color(@Nonnull String string, @Nonnull Color color) {
|
||||
return ChatColor.of(color) + string;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static String color(@Nonnull String string, @Nonnull Color start, @Nonnull Color end) {
|
||||
StringBuilder specialColors = new StringBuilder();
|
||||
for (String color : SPECIAL_COLORS) {
|
||||
if (string.contains(color)) {
|
||||
specialColors.append(color);
|
||||
string = string.replace(color, "");
|
||||
}
|
||||
}
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
ChatColor[] colors = createGradient(start, end, string.length());
|
||||
String[] characters = string.split("");
|
||||
for (int i = 0; i < string.length(); i++) {
|
||||
stringBuilder.append(colors[i]).append(specialColors).append(characters[i]);
|
||||
}
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static String rainbow(@Nonnull String string, float saturation) {
|
||||
StringBuilder specialColors = new StringBuilder();
|
||||
for (String color : SPECIAL_COLORS) {
|
||||
if (string.contains(color)) {
|
||||
specialColors.append(color);
|
||||
string = string.replace(color, "");
|
||||
}
|
||||
}
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
ChatColor[] colors = createRainbow(string.length(), saturation);
|
||||
String[] characters = string.split("");
|
||||
for (int i = 0; i < string.length(); i++) {
|
||||
stringBuilder.append(colors[i]).append(specialColors).append(characters[i]);
|
||||
}
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static ChatColor getColor(@Nonnull String string) {
|
||||
return ChatColor.of(new Color(Integer.parseInt(string, 16)));
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static String stripColorFormatting(@Nonnull String string) {
|
||||
return string.replaceAll("[&§][a-f0-9lnokm]|<[/]?\\w{5,8}(:[0-9A-F]{6})?>", "");
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private static ChatColor[] createRainbow(int step, float saturation) {
|
||||
ChatColor[] colors = new ChatColor[step];
|
||||
double colorStep = (1.00 / step);
|
||||
for (int i = 0; i < step; i++) {
|
||||
Color color = Color.getHSBColor((float) (colorStep * i), saturation, saturation);
|
||||
colors[i] = ChatColor.of(color);
|
||||
}
|
||||
return colors;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private static ChatColor[] createGradient(@Nonnull Color start, @Nonnull Color end, int step) {
|
||||
if (step <= 1) {
|
||||
return new ChatColor[]{ChatColor.WHITE, ChatColor.WHITE, ChatColor.WHITE};
|
||||
}
|
||||
|
||||
ChatColor[] colors = new ChatColor[step];
|
||||
int stepR = Math.abs(start.getRed() - end.getRed()) / (step - 1);
|
||||
int stepG = Math.abs(start.getGreen() - end.getGreen()) / (step - 1);
|
||||
int stepB = Math.abs(start.getBlue() - end.getBlue()) / (step - 1);
|
||||
int[] direction = new int[]{
|
||||
start.getRed() < end.getRed() ? +1 : -1,
|
||||
start.getGreen() < end.getGreen() ? +1 : -1,
|
||||
start.getBlue() < end.getBlue() ? +1 : -1
|
||||
};
|
||||
|
||||
for (int i = 0; i < step; i++) {
|
||||
Color color = new Color(start.getRed() + ((stepR * i) * direction[0]), start.getGreen() + ((stepG * i) * direction[1]), start.getBlue() + ((stepB * i) * direction[2]));
|
||||
colors[i] = ChatColor.of(color);
|
||||
}
|
||||
return colors;
|
||||
}
|
||||
|
||||
|
||||
@Nonnull
|
||||
private static ChatColor getClosestColor(Color color) {
|
||||
Color nearestColor = null;
|
||||
double nearestDistance = Integer.MAX_VALUE;
|
||||
|
||||
for (Color constantColor : COLORS.keySet()) {
|
||||
double distance = Math.pow(color.getRed() - constantColor.getRed(), 2) + Math.pow(color.getGreen() - constantColor.getGreen(), 2) + Math.pow(color.getBlue() - constantColor.getBlue(), 2);
|
||||
if (nearestDistance > distance) {
|
||||
nearestColor = constantColor;
|
||||
nearestDistance = distance;
|
||||
}
|
||||
}
|
||||
return COLORS.get(nearestColor);
|
||||
}
|
||||
|
||||
@ThreadSafe
|
||||
private static class LruCache {
|
||||
|
||||
private final Deque<String> deque = new LinkedList<>();
|
||||
private final Map<String, LruElement> map = new ConcurrentHashMap<>();
|
||||
|
||||
private final int maxSize;
|
||||
|
||||
public LruCache(int maxSize) {
|
||||
this.maxSize = maxSize;
|
||||
}
|
||||
|
||||
public String getResult(String input) {
|
||||
if (input != null && map.containsKey(input)) {
|
||||
LruElement curr = map.get(input);
|
||||
synchronized (deque) {
|
||||
deque.remove(input);
|
||||
deque.addFirst(input);
|
||||
}
|
||||
return curr.getResult();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void put(String input, String result) {
|
||||
if (input == null || result == null) {
|
||||
return;
|
||||
}
|
||||
synchronized (deque) {
|
||||
if (map.containsKey(input)) {
|
||||
deque.remove(input);
|
||||
} else {
|
||||
int size = deque.size();
|
||||
if (size == maxSize && size > 0) {
|
||||
String temp = deque.removeLast();
|
||||
map.remove(temp);
|
||||
}
|
||||
}
|
||||
LruElement newObj = new LruElement(input, result);
|
||||
deque.addFirst(input);
|
||||
map.put(input, newObj);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
LruCache lruCache = (LruCache) o;
|
||||
return maxSize == lruCache.maxSize && deque.equals(lruCache.deque) && map.equals(lruCache.map);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = deque.hashCode();
|
||||
result = 31 * result + map.hashCode();
|
||||
result = 31 * result + maxSize;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private static class LruElement {
|
||||
|
||||
private final String input;
|
||||
private final String result;
|
||||
|
||||
public LruElement(String input, String result) {
|
||||
this.input = input;
|
||||
this.result = result;
|
||||
}
|
||||
|
||||
public String getInput() {
|
||||
return input;
|
||||
}
|
||||
|
||||
public String getResult() {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private static interface Pattern {
|
||||
|
||||
String process(String string);
|
||||
|
||||
}
|
||||
|
||||
private static class GradientPattern implements Pattern {
|
||||
|
||||
private static final java.util.regex.Pattern PATTERN = java.util.regex.Pattern.compile(
|
||||
"[<{]#([A-Fa-f0-9]{6})[}>](((?![<{]#[A-Fa-f0-9]{6}[}>]).)*)[<{]/#([A-Fa-f0-9]{6})[}>]"
|
||||
);
|
||||
|
||||
public String process(String string) {
|
||||
Matcher matcher = PATTERN.matcher(string);
|
||||
while (matcher.find()) {
|
||||
String start = matcher.group(1);
|
||||
String content = matcher.group(2);
|
||||
String end = matcher.group(4);
|
||||
|
||||
string = string.replace(
|
||||
matcher.group(),
|
||||
color(
|
||||
content,
|
||||
new Color(Integer.parseInt(start, 16)),
|
||||
new Color(Integer.parseInt(end, 16))
|
||||
)
|
||||
);
|
||||
}
|
||||
return string;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class RainbowPattern implements Pattern {
|
||||
|
||||
java.util.regex.Pattern pattern = java.util.regex.Pattern.compile("<RAINBOW([0-9]{1,3})>(.*?)</RAINBOW>");
|
||||
|
||||
public String process(String string) {
|
||||
Matcher matcher = pattern.matcher(string);
|
||||
while (matcher.find()) {
|
||||
String saturation = matcher.group(1);
|
||||
String content = matcher.group(2);
|
||||
|
||||
string = string.replace(matcher.group(), rainbow(content, Float.parseFloat(saturation)));
|
||||
}
|
||||
return string;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class SolidPattern implements Pattern {
|
||||
|
||||
public static final java.util.regex.Pattern PATTERN = java.util.regex.Pattern.compile("[<{]#([A-Fa-f0-9]{6})[}>]|[&]?#([A-Fa-f0-9]{6})");
|
||||
|
||||
public String process(String string) {
|
||||
Matcher matcher = PATTERN.matcher(string);
|
||||
while (matcher.find()) {
|
||||
String color = matcher.group(1);
|
||||
if (color == null) {
|
||||
color = matcher.group(2);
|
||||
}
|
||||
|
||||
string = string.replace(matcher.group(), getColor(color) + "");
|
||||
}
|
||||
return string;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,7 +1,10 @@
|
|||
package com.io.yutian.elementoriginlib.util;
|
||||
|
||||
import com.io.yutian.elementoriginlib.ElementOriginLib;
|
||||
import com.io.yutian.elementoriginlib.logger.Logger;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import com.mojang.authlib.properties.Property;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.attribute.Attribute;
|
||||
import org.bukkit.attribute.AttributeModifier;
|
||||
|
@ -10,11 +13,10 @@ import org.bukkit.enchantments.Enchantment;
|
|||
import org.bukkit.inventory.EquipmentSlot;
|
||||
import org.bukkit.inventory.ItemFlag;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.EnchantmentStorageMeta;
|
||||
import org.bukkit.inventory.meta.FireworkMeta;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.bukkit.inventory.meta.SkullMeta;
|
||||
import org.bukkit.inventory.meta.*;
|
||||
import org.bukkit.inventory.meta.trim.ArmorTrim;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.*;
|
||||
|
@ -23,168 +25,40 @@ public class ItemStackBuilder {
|
|||
|
||||
private ItemStack itemStack;
|
||||
|
||||
private Material type;
|
||||
|
||||
private int amount;
|
||||
|
||||
private short data;
|
||||
|
||||
private ItemMeta meta;
|
||||
|
||||
private String displayName;
|
||||
|
||||
private int customModelData;
|
||||
|
||||
private List<String> lore;
|
||||
|
||||
private Map<Enchantment, Integer> enchants;
|
||||
|
||||
private Set<ItemFlag> itemFlags;
|
||||
|
||||
private List<PotionEffect> potionEffects;
|
||||
private List<Pattern> patterns;
|
||||
private List<FireworkEffect> fireworkEffects;
|
||||
private String skullTextures;
|
||||
private UUID skullOwner;
|
||||
|
||||
public ItemStackBuilder(Material material) {
|
||||
this.itemStack = new ItemStack(material);
|
||||
this.type = material;
|
||||
this.amount = 1;
|
||||
this.data = 0;
|
||||
this.meta = this.itemStack.getItemMeta();
|
||||
this.displayName = this.meta.getDisplayName();
|
||||
this.customModelData = this.meta.hasCustomModelData() ? this.meta.getCustomModelData() : -1;
|
||||
this.lore = new ArrayList<>();
|
||||
this.enchants = new HashMap<>();
|
||||
this.itemFlags = new HashSet<>();
|
||||
this.potionEffects = new ArrayList<>();
|
||||
this.patterns = new ArrayList<>();
|
||||
this.fireworkEffects = new ArrayList<>();
|
||||
}
|
||||
|
||||
public ItemStackBuilder(ItemStack item) {
|
||||
this.itemStack = item.clone();
|
||||
this.type = item.getType();
|
||||
this.amount = item.getAmount();
|
||||
this.data = item.getDurability();
|
||||
this.meta = item.getItemMeta();
|
||||
this.displayName = this.meta.getDisplayName();
|
||||
this.customModelData = this.meta.hasCustomModelData() ? this.meta.getCustomModelData() : -1;
|
||||
this.lore = this.meta.getLore() == null ? new ArrayList<>() : meta.getLore();
|
||||
this.enchants = this.meta.getEnchants();
|
||||
this.itemFlags = this.meta.getItemFlags();
|
||||
this.potionEffects = new ArrayList<>();
|
||||
this.patterns = new ArrayList<>();
|
||||
this.fireworkEffects = new ArrayList<>();
|
||||
}
|
||||
|
||||
public ItemStack build() {
|
||||
ItemStack item = new ItemStack(type, amount);
|
||||
item.setType(type);
|
||||
item.setAmount(amount);
|
||||
ItemMeta itemMeta = item.getItemMeta();
|
||||
if (displayName != null) {
|
||||
itemMeta.setDisplayName(ChatColor.translateAlternateColorCodes('&', displayName));
|
||||
}
|
||||
if (enchants != null) {
|
||||
item.addUnsafeEnchantments(enchants);
|
||||
}
|
||||
if (lore != null) {
|
||||
List<String> l = new ArrayList<>();
|
||||
lore.forEach((s) -> {
|
||||
l.add(ChatColor.translateAlternateColorCodes('&', s));
|
||||
});
|
||||
itemMeta.setLore(l);
|
||||
}
|
||||
if (this.customModelData != -1) {
|
||||
itemMeta.setCustomModelData(customModelData);
|
||||
}
|
||||
if (itemFlags != null) {
|
||||
for (ItemFlag flag : itemFlags) {
|
||||
itemMeta.addItemFlags(flag);
|
||||
}
|
||||
}
|
||||
if (fireworkEffects != null && fireworkEffects.size() > 0 && (type.equals(Material.FIREWORK_STAR) || type.equals(Material.FIREWORK_ROCKET))) {
|
||||
FireworkMeta fireworkMeta = (FireworkMeta) itemMeta;
|
||||
for (FireworkEffect effect : fireworkEffects) {
|
||||
fireworkMeta.addEffect(effect);
|
||||
}
|
||||
}
|
||||
if (skullTextures != null && type.equals(Material.PLAYER_HEAD)) {
|
||||
SkullMeta skullMeta = (SkullMeta) itemMeta;
|
||||
String uuid = UUID.randomUUID().toString();
|
||||
|
||||
GameProfile profile = new GameProfile(UUID.fromString(uuid), null);
|
||||
profile.getProperties().put("textures", new Property("textures", skullTextures));
|
||||
Field profileField;
|
||||
try {
|
||||
profileField = skullMeta.getClass().getDeclaredField("profile");
|
||||
profileField.setAccessible(true);
|
||||
profileField.set(skullMeta, profile);
|
||||
} catch (NullPointerException | NoSuchFieldException | IllegalArgumentException | IllegalAccessException e1) {
|
||||
}
|
||||
} else if (skullOwner != null && type.equals(Material.PLAYER_HEAD)) {
|
||||
SkullMeta skullMeta = (SkullMeta) itemMeta;
|
||||
OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(skullOwner);
|
||||
if (offlinePlayer != null) {
|
||||
skullMeta.setOwningPlayer(Bukkit.getOfflinePlayer(skullOwner));
|
||||
}
|
||||
}
|
||||
item.setItemMeta(itemMeta);
|
||||
return item;
|
||||
return itemStack;
|
||||
}
|
||||
|
||||
public int getAmount() {
|
||||
return amount;
|
||||
return itemStack.getAmount();
|
||||
}
|
||||
|
||||
public Material getType() {
|
||||
return type;
|
||||
return itemStack.getType();
|
||||
}
|
||||
|
||||
public List<String> getLore() {
|
||||
return lore;
|
||||
public List<Component> getLore() {
|
||||
return itemStack.getItemMeta().lore();
|
||||
}
|
||||
|
||||
public int getCustomModelData() {
|
||||
return customModelData;
|
||||
return itemStack.getItemMeta().getCustomModelData();
|
||||
}
|
||||
|
||||
public Map<Enchantment, Integer> getEnchants() {
|
||||
return enchants;
|
||||
return itemStack.getItemMeta().getEnchants();
|
||||
}
|
||||
|
||||
public Set<ItemFlag> getItemFlags() {
|
||||
return itemFlags;
|
||||
}
|
||||
|
||||
public List<PotionEffect> getPotionEffects() {
|
||||
return potionEffects;
|
||||
}
|
||||
|
||||
public List<FireworkEffect> getFireworkEffects() {
|
||||
return fireworkEffects;
|
||||
}
|
||||
|
||||
public List<Pattern> getPatterns() {
|
||||
return patterns;
|
||||
}
|
||||
|
||||
public String getSkullTextures() {
|
||||
return skullTextures;
|
||||
}
|
||||
|
||||
public String getDisplayName() {
|
||||
return displayName;
|
||||
}
|
||||
|
||||
public short getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public UUID getSkullOwner() {
|
||||
return skullOwner;
|
||||
return itemStack.getItemMeta().getItemFlags();
|
||||
}
|
||||
|
||||
public ItemStackBuilder setItemStack(ItemStack item) {
|
||||
|
@ -193,189 +67,285 @@ public class ItemStackBuilder {
|
|||
}
|
||||
|
||||
public ItemStackBuilder setType(Material type) {
|
||||
this.type = type;
|
||||
this.itemStack.withType(type);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackBuilder setCustomModelData(int customModelData) {
|
||||
this.customModelData = customModelData;
|
||||
this.itemStack.editMeta((meta)-> meta.setCustomModelData(customModelData));
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackBuilder setAmount(int amount) {
|
||||
this.amount = amount;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackBuilder setData(int data) {
|
||||
if (data > 255) {
|
||||
data = 255;
|
||||
}
|
||||
this.data = (short) data;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackBuilder setData(short data) {
|
||||
this.data = data;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackBuilder setItemMeta(ItemMeta meta) {
|
||||
this.meta = meta;
|
||||
this.itemStack.setAmount(amount);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackBuilder setDisplayName(String name) {
|
||||
this.displayName = name;
|
||||
this.itemStack.editMeta((meta)-> meta.displayName(Component.text(name)));
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackBuilder setDisplayName(Component name) {
|
||||
this.itemStack.editMeta((meta)-> meta.displayName(name));
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackBuilder setLore(List<String> loreList) {
|
||||
this.lore = loreList;
|
||||
List<Component> loreComponents = new ArrayList<>();
|
||||
for (String lore : loreList) {
|
||||
loreComponents.add(Component.text(lore));
|
||||
}
|
||||
this.itemStack.editMeta((meta)-> meta.lore(loreComponents));
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackBuilder setLore(String... lores) {
|
||||
this.lore = new ArrayList<>(Arrays.asList(lores));
|
||||
return this;
|
||||
return setLore(List.of(lores));
|
||||
}
|
||||
|
||||
public ItemStackBuilder addLore(String lore) {
|
||||
this.lore.add(lore);
|
||||
List<Component> loreComponents = itemStack.getItemMeta().hasLore() ? itemStack.getItemMeta().lore() : new ArrayList<>();
|
||||
loreComponents.add(Component.text(lore));
|
||||
this.itemStack.editMeta((meta)-> meta.lore(loreComponents));
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackBuilder addLore(String... lores) {
|
||||
this.lore.addAll(Arrays.asList(lores));
|
||||
List<Component> loreComponents = itemStack.getItemMeta().hasLore() ? itemStack.getItemMeta().lore() : new ArrayList<>();
|
||||
for (String lore : lores) {
|
||||
loreComponents.add(Component.text(lore));
|
||||
}
|
||||
this.itemStack.editMeta((meta)-> meta.lore(loreComponents));
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackBuilder addLore(List<String> lores) {
|
||||
for (String lore : lores) {
|
||||
this.lore.add(lore);
|
||||
public ItemStackBuilder addLore(Component... lores) {
|
||||
List<Component> loreComponents = itemStack.getItemMeta().hasLore() ? itemStack.getItemMeta().lore() : new ArrayList<>();
|
||||
for (Component lore : lores) {
|
||||
loreComponents.add(lore);
|
||||
}
|
||||
this.itemStack.editMeta((meta)-> meta.lore(loreComponents));
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackBuilder addLore(List<Component> lores) {
|
||||
List<Component> loreComponents = itemStack.getItemMeta().hasLore() ? itemStack.getItemMeta().lore() : new ArrayList<>();
|
||||
loreComponents.addAll(lores);
|
||||
this.itemStack.editMeta((meta)-> meta.lore(loreComponents));
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackBuilder addAttributeModifier(Attribute attribute, AttributeModifier attributeModifier) {
|
||||
this.meta.addAttributeModifier(attribute, attributeModifier);
|
||||
this.itemStack.editMeta((meta)-> meta.addAttributeModifier(attribute, attributeModifier));
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackBuilder removeAttributeModifier(Attribute attribute) {
|
||||
this.meta.removeAttributeModifier(attribute);
|
||||
this.itemStack.editMeta((meta)-> meta.removeAttributeModifier(attribute));
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackBuilder removeAttributeModifier(EquipmentSlot equipmentSlot) {
|
||||
this.meta.removeAttributeModifier(equipmentSlot);
|
||||
this.itemStack.editMeta((meta)-> meta.removeAttributeModifier(equipmentSlot));
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackBuilder removeAttributeModifier(Attribute attribute, AttributeModifier attributeModifier) {
|
||||
this.meta.removeAttributeModifier(attribute, attributeModifier);
|
||||
this.itemStack.editMeta((meta)-> meta.removeAttributeModifier(attribute, attributeModifier));
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackBuilder addEnchant(Enchantment ench, int level) {
|
||||
this.enchants.put(ench, level);
|
||||
this.itemStack.editMeta((meta)-> meta.addEnchant(ench, level, true));
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackBuilder removeEnchant(Enchantment ench) {
|
||||
this.enchants.remove(ench);
|
||||
this.itemStack.editMeta((meta)-> meta.removeEnchant(ench));
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackBuilder setEnchants(Map<Enchantment, Integer> enchants) {
|
||||
this.enchants = enchants;
|
||||
return this;
|
||||
this.itemStack.editMeta((meta)->{
|
||||
meta.removeEnchantments();
|
||||
for (Map.Entry<Enchantment, Integer> entry : enchants.entrySet()) {
|
||||
meta.addEnchant(entry.getKey(), entry.getValue(), true);
|
||||
}
|
||||
|
||||
public ItemStackBuilder setEnchants(List<String> enchants) {
|
||||
this.enchants = getEnchantsFromList(enchants);
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackBuilder setItemFlags(Set<ItemFlag> itemFlags) {
|
||||
this.itemFlags = itemFlags;
|
||||
this.itemStack.editMeta((meta)-> {
|
||||
meta.removeItemFlags(ItemFlag.values());
|
||||
for (ItemFlag itemFlag : itemFlags) {
|
||||
meta.addItemFlags(itemFlag);
|
||||
}
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackBuilder addItemFlags(ItemFlag[] itemFlags) {
|
||||
this.itemFlags.addAll(Arrays.asList(itemFlags));
|
||||
this.itemStack.editMeta((meta)-> {
|
||||
meta.removeItemFlags(ItemFlag.values());
|
||||
for (ItemFlag itemFlag : itemFlags) {
|
||||
meta.addItemFlags(itemFlag);
|
||||
}
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackBuilder addItemFlags(ItemFlag itemFlag) {
|
||||
this.itemFlags.add(itemFlag);
|
||||
this.itemStack.editMeta((meta)-> meta.addItemFlags(itemFlag));
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackBuilder setUnbreakable(boolean unbreakable) {
|
||||
this.itemStack.editMeta((meta)-> meta.setUnbreakable(unbreakable));
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackBuilder setHideTooltip(boolean hideTooltip) {
|
||||
this.itemStack.editMeta((meta)-> meta.setHideTooltip(hideTooltip));
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackBuilder setFireResistant(boolean fireResistant) {
|
||||
this.itemStack.editMeta((meta)-> meta.setFireResistant(fireResistant));
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackBuilder setMaxStackSize(int maxStackSize) {
|
||||
this.itemStack.editMeta((meta)-> meta.setCustomModelData(maxStackSize));
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackBuilder setEnchantmentGlint(boolean enchantmentGlint) {
|
||||
this.itemStack.editMeta((meta)-> meta.setEnchantmentGlintOverride(enchantmentGlint));
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackBuilder addPotionEffect(PotionEffect potionEffect) {
|
||||
this.potionEffects.add(potionEffect);
|
||||
if (!(itemStack.getItemMeta() instanceof PotionMeta)) {
|
||||
ElementOriginLib.LOGGER.warn("ItemMeta is not " + PotionMeta.class.getName());
|
||||
return this;
|
||||
}
|
||||
this.itemStack.editMeta(PotionMeta.class, (meta)-> meta.addCustomEffect(potionEffect, true));
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackBuilder removePotionEffect(PotionEffect potionEffect) {
|
||||
if (!(itemStack.getItemMeta() instanceof PotionMeta)) {
|
||||
ElementOriginLib.LOGGER.warn("ItemMeta is not " + PotionMeta.class.getName());
|
||||
return this;
|
||||
}
|
||||
this.itemStack.editMeta(PotionMeta.class, (meta)-> meta.removeCustomEffect(potionEffect.getType()));
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackBuilder clearPotionEffects() {
|
||||
if (!(itemStack.getItemMeta() instanceof PotionMeta)) {
|
||||
ElementOriginLib.LOGGER.warn("ItemMeta is not " + PotionMeta.class.getName());
|
||||
return this;
|
||||
}
|
||||
this.itemStack.editMeta(PotionMeta.class, (meta)-> {
|
||||
meta.clearCustomEffects();
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackBuilder addPattern(Pattern pattern) {
|
||||
this.patterns.add(pattern);
|
||||
if (!(itemStack.getItemMeta() instanceof BannerMeta)) {
|
||||
ElementOriginLib.LOGGER.warn("ItemMeta is not " + BannerMeta.class.getName());
|
||||
return this;
|
||||
}
|
||||
this.itemStack.editMeta(BannerMeta.class, (meta)-> meta.addPattern(pattern));
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackBuilder addFireworkEffect(FireworkEffect fireworkEffect) {
|
||||
this.fireworkEffects.add(fireworkEffect);
|
||||
public ItemStackBuilder removePattern(int index) {
|
||||
if (!(itemStack.getItemMeta() instanceof BannerMeta)) {
|
||||
ElementOriginLib.LOGGER.warn("ItemMeta is not " + BannerMeta.class.getName());
|
||||
return this;
|
||||
}
|
||||
this.itemStack.editMeta(BannerMeta.class, (meta)-> meta.removePattern(index));
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackBuilder setPatterns(List<Pattern> patterns) {
|
||||
if (!(itemStack.getItemMeta() instanceof BannerMeta)) {
|
||||
ElementOriginLib.LOGGER.warn("ItemMeta is not " + BannerMeta.class.getName());
|
||||
return this;
|
||||
}
|
||||
this.itemStack.editMeta(BannerMeta.class, (meta)-> meta.setPatterns(patterns));
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackBuilder setFireworkEffect(FireworkEffect fireworkEffect) {
|
||||
if (!(itemStack.getItemMeta() instanceof FireworkMeta)) {
|
||||
ElementOriginLib.LOGGER.warn("ItemMeta is not " + FireworkMeta.class.getName());
|
||||
return this;
|
||||
}
|
||||
this.itemStack.editMeta(FireworkMeta.class, (meta)-> meta.addEffect(fireworkEffect));
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackBuilder clearFireworkEffects() {
|
||||
if (!(itemStack.getItemMeta() instanceof FireworkMeta)) {
|
||||
ElementOriginLib.LOGGER.warn("ItemMeta is not " + FireworkMeta.class.getName());
|
||||
return this;
|
||||
}
|
||||
this.itemStack.editMeta(FireworkMeta.class, (meta)-> meta.clearEffects());
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackBuilder setSkullTextures(String skullTextures) {
|
||||
this.skullTextures = skullTextures;
|
||||
if (!(itemStack.getItemMeta() instanceof SkullMeta)) {
|
||||
ElementOriginLib.LOGGER.warn("ItemMeta is not " + SkullMeta.class.getName());
|
||||
return this;
|
||||
}
|
||||
this.itemStack.editMeta(SkullMeta.class, (meta)-> {
|
||||
String uuid = UUID.randomUUID().toString();
|
||||
|
||||
GameProfile profile = new GameProfile(UUID.fromString(uuid), "Skull");
|
||||
profile.getProperties().put("textures", new Property("textures", skullTextures));
|
||||
Field profileField;
|
||||
try {
|
||||
profileField = meta.getClass().getDeclaredField("profile");
|
||||
profileField.setAccessible(true);
|
||||
profileField.set(meta, profile);
|
||||
} catch (NullPointerException | NoSuchFieldException | IllegalArgumentException | IllegalAccessException e1) {
|
||||
}
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackBuilder setSkullOwner(UUID skullOwner) {
|
||||
this.skullOwner = skullOwner;
|
||||
public ItemStackBuilder setSkullOwner(String skullOwner) {
|
||||
if (!(itemStack.getItemMeta() instanceof SkullMeta)) {
|
||||
ElementOriginLib.LOGGER.warn("ItemMeta is not " + SkullMeta.class.getName());
|
||||
return this;
|
||||
}
|
||||
this.itemStack.editMeta(SkullMeta.class, (meta)-> meta.setOwningPlayer(Bukkit.getOfflinePlayer(skullOwner)));
|
||||
return this;
|
||||
}
|
||||
|
||||
protected Map<Enchantment, Integer> getEnchantsFromList(List<String> enchants) {
|
||||
Map<Enchantment, Integer> map = new HashMap<>();
|
||||
if (enchants == null) {
|
||||
return map;
|
||||
public ItemStackBuilder setColor(Color color) {
|
||||
if (!(itemStack.getItemMeta() instanceof LeatherArmorMeta)) {
|
||||
ElementOriginLib.LOGGER.warn("ItemMeta is not " + LeatherArmorMeta.class.getName());
|
||||
return this;
|
||||
}
|
||||
for (String s : enchants) {
|
||||
if (s.contains(":")) {
|
||||
String[] part = s.split(":");
|
||||
Enchantment en = Enchantment.getByName(part[0]);
|
||||
if (en == null) {
|
||||
continue;
|
||||
}
|
||||
map.put(en, Integer.parseInt(part[1]));
|
||||
}
|
||||
}
|
||||
return map;
|
||||
this.itemStack.editMeta(LeatherArmorMeta.class, (meta)-> meta.setColor(color));
|
||||
return this;
|
||||
}
|
||||
|
||||
protected static ItemStack setEnchants(ItemStack stack, List<String> enchants) {
|
||||
if (enchants == null) {
|
||||
return stack;
|
||||
public ItemStackBuilder setTrim(ArmorTrim trim) {
|
||||
if (!(itemStack.getItemMeta() instanceof ArmorMeta)) {
|
||||
ElementOriginLib.LOGGER.warn("ItemMeta is not " + ArmorMeta.class.getName());
|
||||
return this;
|
||||
}
|
||||
for (String s : enchants) {
|
||||
if (s.contains(":")) {
|
||||
String[] part = s.split(":");
|
||||
Enchantment en = Enchantment.getByName(part[0]);
|
||||
if (en == null) {
|
||||
continue;
|
||||
}
|
||||
if (stack.getType() != Material.ENCHANTED_BOOK) {
|
||||
stack.addUnsafeEnchantment(en, Integer.parseInt(part[1]));
|
||||
} else {
|
||||
EnchantmentStorageMeta esm = (EnchantmentStorageMeta) stack.getItemMeta();
|
||||
esm.addStoredEnchant(en, Integer.parseInt(part[1]), true);
|
||||
stack.setItemMeta((ItemMeta) esm);
|
||||
}
|
||||
}
|
||||
}
|
||||
return stack;
|
||||
this.itemStack.editMeta(ArmorMeta.class, (meta)-> meta.setTrim(trim));
|
||||
return this;
|
||||
}
|
||||
|
||||
private void setField(Object instance, String name, Object value) throws ReflectiveOperationException {
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
package com.io.yutian.elementoriginlib.util;
|
||||
|
||||
import com.io.yutian.elementoriginlib.ElementOriginLib;
|
||||
import com.io.yutian.elementoriginlib.expiringmap.ExpirationPolicy;
|
||||
import com.io.yutian.elementoriginlib.expiringmap.ExpiringMap;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class LangUtil {
|
||||
|
||||
private static ExpiringMap<String, String> expiringMap = ExpiringMap.builder().expiration(3, TimeUnit.MINUTES).expirationPolicy(ExpirationPolicy.CREATED).build();
|
||||
private static Map<String, String> expiringMap = new HashMap<>();
|
||||
private static JSONObject jsonObject = new JSONObject();
|
||||
|
||||
public static String getLang(String key) {
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
package com.io.yutian.elementoriginlib.util;
|
||||
|
||||
import org.bukkit.Material;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class SkullBuilder extends ItemStackBuilder {
|
||||
|
||||
public SkullBuilder() {
|
||||
super(Material.PLAYER_HEAD);
|
||||
}
|
||||
|
||||
public SkullBuilder(String textures) {
|
||||
super(Material.PLAYER_HEAD);
|
||||
setSkullTextures(textures);
|
||||
}
|
||||
|
||||
public SkullBuilder(UUID uuid) {
|
||||
super(Material.PLAYER_HEAD);
|
||||
setSkullOwner(uuid);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,347 @@
|
|||
package com.io.yutian.elementoriginlib.util;
|
||||
|
||||
import com.io.yutian.elementoriginlib.exception.ItemStatDataLoadException;
|
||||
import com.io.yutian.elementoriginlib.item.stat.data.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class StatDataUtil {
|
||||
|
||||
public static BooleanData loadBooleanDataAsObject(@NotNull Object value) throws ItemStatDataLoadException {
|
||||
if (Objects.isNull(value)) {
|
||||
throw new ItemStatDataLoadException("Invalid value: null");
|
||||
}
|
||||
try {
|
||||
if (value instanceof Boolean bool) {
|
||||
return new BooleanData(bool);
|
||||
} else if (value instanceof String arg) {
|
||||
boolean parsed = Boolean.parseBoolean(arg);
|
||||
if (!arg.equalsIgnoreCase("true") && !arg.equalsIgnoreCase("false")) {
|
||||
throw new ItemStatDataLoadException("Invalid boolean string: " + arg);
|
||||
}
|
||||
return new BooleanData(parsed);
|
||||
} else if (value instanceof Byte b) {
|
||||
return new BooleanData(b == 1);
|
||||
} else if (value instanceof Integer i) {
|
||||
return new BooleanData(i == 1);
|
||||
} else {
|
||||
throw new ItemStatDataLoadException("Invalid boolean value: " + value);
|
||||
}
|
||||
} catch (ClassCastException e) {
|
||||
throw new ItemStatDataLoadException("Invalid type: " + value.getClass(), e);
|
||||
}
|
||||
}
|
||||
|
||||
public static DoubleListData loadDoubleListDataAsObject(@NotNull Object value) throws ItemStatDataLoadException {
|
||||
if (Objects.isNull(value)) {
|
||||
throw new ItemStatDataLoadException("Invalid value: null");
|
||||
}
|
||||
try {
|
||||
if (value instanceof List<?> list) {
|
||||
List<Double> doubleList = new ArrayList<>();
|
||||
for (Object item : list) {
|
||||
if (item instanceof Double d) {
|
||||
doubleList.add(d);
|
||||
} else if (item instanceof String str) {
|
||||
try {
|
||||
doubleList.add(Double.parseDouble(str));
|
||||
} catch (NumberFormatException e) {
|
||||
throw new ItemStatDataLoadException("Invalid string value for Double: " + str, e);
|
||||
}
|
||||
} else {
|
||||
throw new ItemStatDataLoadException("List contains non-double element: " + item);
|
||||
}
|
||||
}
|
||||
return new DoubleListData(doubleList);
|
||||
} else if (value instanceof double[] array) {
|
||||
List<Double> doubleList = new ArrayList<>();
|
||||
for (double d : array) {
|
||||
doubleList.add(d);
|
||||
}
|
||||
return new DoubleListData(doubleList);
|
||||
} else if (value instanceof Double[] array) {
|
||||
List<Double> doubleList = new ArrayList<>(Arrays.asList(array));
|
||||
return new DoubleListData(doubleList);
|
||||
} else if (value instanceof String str) {
|
||||
List<Double> doubleList = new ArrayList<>();
|
||||
String[] items = str.split(",");
|
||||
for (String item : items) {
|
||||
try {
|
||||
doubleList.add(Double.parseDouble(item.trim()));
|
||||
} catch (NumberFormatException e) {
|
||||
throw new ItemStatDataLoadException("Invalid number format in string: " + item, e);
|
||||
}
|
||||
}
|
||||
return new DoubleListData(doubleList);
|
||||
} else {
|
||||
throw new ItemStatDataLoadException("Invalid value type for DoubleListData: " + value);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new ItemStatDataLoadException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static DoubleData loadDoubleDataAsObject(@NotNull Object value) throws ItemStatDataLoadException {
|
||||
if (Objects.isNull(value)) {
|
||||
throw new ItemStatDataLoadException("Invalid value: null");
|
||||
}
|
||||
try {
|
||||
if (value instanceof Double d) {
|
||||
return new DoubleData(d);
|
||||
} else if (value instanceof String arg) {
|
||||
try {
|
||||
return new DoubleData(Double.parseDouble(arg));
|
||||
} catch (NumberFormatException e) {
|
||||
throw new ItemStatDataLoadException("Invalid double string: " + arg, e);
|
||||
}
|
||||
} else if (value instanceof Byte b) {
|
||||
return new DoubleData((double) b);
|
||||
} else if (value instanceof Integer i) {
|
||||
return new DoubleData((double) i);
|
||||
} else if (value instanceof Long l) {
|
||||
return new DoubleData((double) l);
|
||||
} else {
|
||||
throw new ItemStatDataLoadException("Invalid double value: " + value);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new ItemStatDataLoadException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static <E extends Enum> EnumListData<E> loadEnumListDataAsObject(Class<E> clazz, @NotNull Object value) throws ItemStatDataLoadException {
|
||||
if (Objects.isNull(value)) {
|
||||
throw new ItemStatDataLoadException("Invalid value: null");
|
||||
}
|
||||
try {
|
||||
if (value instanceof List<?> list) {
|
||||
List<E> enumList = new ArrayList<>();
|
||||
for (Object item : list) {
|
||||
if (item instanceof String str) {
|
||||
try {
|
||||
E enumConstant = (E) Enum.valueOf(clazz, str);
|
||||
enumList.add(enumConstant);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new ItemStatDataLoadException("Invalid enum string: " + str, e);
|
||||
}
|
||||
} else if (item instanceof Integer i) {
|
||||
E[] enumConstants = clazz.getEnumConstants();
|
||||
if (i < 0 || i >= enumConstants.length) {
|
||||
throw new ItemStatDataLoadException("Invalid enum ordinal: " + i);
|
||||
}
|
||||
enumList.add(enumConstants[i]);
|
||||
} else if (item instanceof Enum<?> enumItem) {
|
||||
enumList.add((E) enumItem);
|
||||
} else {
|
||||
throw new ItemStatDataLoadException("Invalid list element type: " + item);
|
||||
}
|
||||
}
|
||||
return new EnumListData<>(enumList);
|
||||
} else if (value instanceof String str) {
|
||||
List<E> enumList = new ArrayList<>();
|
||||
String[] enumNames = str.split(",");
|
||||
for (String enumName : enumNames) {
|
||||
try {
|
||||
E enumConstant = (E) Enum.valueOf(clazz, enumName.trim());
|
||||
enumList.add(enumConstant);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new ItemStatDataLoadException("Invalid enum string: " + enumName, e);
|
||||
}
|
||||
}
|
||||
return new EnumListData<>(enumList);
|
||||
} else {
|
||||
throw new ItemStatDataLoadException("Invalid value type for EnumListData: " + value);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new ItemStatDataLoadException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static <E extends Enum> EnumData<E> loadEnumDataAsObject(Class<E> clazz, @NotNull Object value) throws ItemStatDataLoadException {
|
||||
if (Objects.isNull(value)) {
|
||||
throw new ItemStatDataLoadException("Invalid value: null");
|
||||
}
|
||||
try {
|
||||
if (value instanceof Enum<?> enumValue) {
|
||||
return new EnumData<>((E) enumValue);
|
||||
} else if (value instanceof String str) {
|
||||
try {
|
||||
E enumConstant = (E) Enum.valueOf(clazz, str);
|
||||
return new EnumData<>(enumConstant);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new ItemStatDataLoadException("Invalid enum string: " + str, e);
|
||||
}
|
||||
} else if (value instanceof Integer i) {
|
||||
E[] enumConstants = clazz.getEnumConstants();
|
||||
if (i < 0 || i >= enumConstants.length) {
|
||||
throw new ItemStatDataLoadException("Invalid enum ordinal: " + i);
|
||||
}
|
||||
return new EnumData<>(enumConstants[i]);
|
||||
} else {
|
||||
throw new ItemStatDataLoadException("Invalid value type for EnumData: " + value);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new ItemStatDataLoadException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static IntListData loadIntListDataAsObject(@NotNull Object value) throws ItemStatDataLoadException {
|
||||
if (Objects.isNull(value)) {
|
||||
throw new ItemStatDataLoadException("Invalid value: null");
|
||||
}
|
||||
try {
|
||||
if (value instanceof List<?> list) {
|
||||
List<Integer> intList = new ArrayList<>();
|
||||
for (Object item : list) {
|
||||
if (item instanceof Integer i) {
|
||||
intList.add(i);
|
||||
} else {
|
||||
throw new ItemStatDataLoadException("List contains non-integer element: " + item);
|
||||
}
|
||||
}
|
||||
return new IntListData(intList);
|
||||
} else if (value instanceof int[] array) {
|
||||
List<Integer> intList = new ArrayList<>();
|
||||
for (int i : array) {
|
||||
intList.add(i);
|
||||
}
|
||||
return new IntListData(intList);
|
||||
} else if (value instanceof String str) {
|
||||
try {
|
||||
List<Integer> intList = new ArrayList<>();
|
||||
String[] items = str.split(",");
|
||||
for (String item : items) {
|
||||
intList.add(Integer.parseInt(item.trim()));
|
||||
}
|
||||
return new IntListData(intList);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new ItemStatDataLoadException("Invalid integer string: " + str, e);
|
||||
}
|
||||
} else {
|
||||
throw new ItemStatDataLoadException("Invalid value type for IntListData: " + value);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new ItemStatDataLoadException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static IntData loadIntDataAsObject(@NotNull Object value) throws ItemStatDataLoadException {
|
||||
if (Objects.isNull(value)) {
|
||||
throw new ItemStatDataLoadException("Invalid value: null");
|
||||
}
|
||||
try {
|
||||
if (value instanceof Integer i) {
|
||||
return new IntData(i);
|
||||
} else if (value instanceof String arg) {
|
||||
try {
|
||||
return new IntData(Integer.parseInt(arg));
|
||||
} catch (NumberFormatException e) {
|
||||
throw new ItemStatDataLoadException("Invalid integer string: " + arg, e);
|
||||
}
|
||||
} else if (value instanceof Byte b) {
|
||||
return new IntData((int) b);
|
||||
} else if (value instanceof Long l) {
|
||||
if (l < Integer.MIN_VALUE || l > Integer.MAX_VALUE) {
|
||||
throw new ItemStatDataLoadException("Long value out of range for integer: " + l);
|
||||
}
|
||||
return new IntData(l.intValue());
|
||||
} else if (value instanceof Double d) {
|
||||
if (d < Integer.MIN_VALUE || d > Integer.MAX_VALUE) {
|
||||
throw new ItemStatDataLoadException("Double value out of range for integer: " + d);
|
||||
}
|
||||
return new IntData((int) d.doubleValue());
|
||||
} else if (value instanceof Float f) {
|
||||
if (f < Integer.MIN_VALUE || f > Integer.MAX_VALUE) {
|
||||
throw new ItemStatDataLoadException("Float value out of range for integer: " + f);
|
||||
}
|
||||
return new IntData((int) f.floatValue());
|
||||
} else {
|
||||
throw new ItemStatDataLoadException("Invalid integer value: " + value);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new ItemStatDataLoadException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static MapData loadMapDataAsObject(@NotNull Object value) throws ItemStatDataLoadException {
|
||||
if (Objects.isNull(value)) {
|
||||
throw new ItemStatDataLoadException("Invalid value: null");
|
||||
}
|
||||
try {
|
||||
if (value instanceof Map<?, ?> map) {
|
||||
Map<String, Object> resultMap = new HashMap<>();
|
||||
for (Map.Entry<?, ?> entry : map.entrySet()) {
|
||||
if (entry.getKey() instanceof String key) {
|
||||
resultMap.put(key, entry.getValue());
|
||||
} else {
|
||||
throw new ItemStatDataLoadException("Map key is not a String: " + entry.getKey());
|
||||
}
|
||||
}
|
||||
return new MapData(resultMap);
|
||||
} else {
|
||||
throw new ItemStatDataLoadException("Invalid value type for MapData: " + value);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new ItemStatDataLoadException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static StringListData loadStringListDataAsObject(@NotNull Object value) throws ItemStatDataLoadException {
|
||||
if (Objects.isNull(value)) {
|
||||
throw new ItemStatDataLoadException("Invalid value: null");
|
||||
}
|
||||
try {
|
||||
if (value instanceof List<?> list) {
|
||||
List<String> stringList = new ArrayList<>();
|
||||
for (Object item : list) {
|
||||
if (item instanceof String str) {
|
||||
stringList.add(str);
|
||||
} else {
|
||||
throw new ItemStatDataLoadException("List contains non-string element: " + item);
|
||||
}
|
||||
}
|
||||
return new StringListData(stringList);
|
||||
} else if (value instanceof String[] array) {
|
||||
// 处理 String[] 类型
|
||||
return new StringListData(Arrays.asList(array));
|
||||
} else if (value instanceof String str) {
|
||||
List<String> stringList = new ArrayList<>();
|
||||
stringList.add(str);
|
||||
return new StringListData(stringList);
|
||||
} else {
|
||||
throw new ItemStatDataLoadException("Invalid value type for StringListData: " + value);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new ItemStatDataLoadException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static StringData loadStringDataAsObject(@NotNull Object value) {
|
||||
if (Objects.isNull(value)) {
|
||||
throw new ItemStatDataLoadException("Invalid value: null");
|
||||
}
|
||||
return new StringData(value.toString());
|
||||
}
|
||||
|
||||
public static UUIDData loadUUIDDataAsObject(@NotNull Object value) throws ItemStatDataLoadException {
|
||||
if (Objects.isNull(value)) {
|
||||
throw new ItemStatDataLoadException("Invalid value: null");
|
||||
}
|
||||
try {
|
||||
if (value instanceof UUID uuid) {
|
||||
return new UUIDData(uuid);
|
||||
} else if (value instanceof String str) {
|
||||
try {
|
||||
return new UUIDData(UUID.fromString(str));
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new ItemStatDataLoadException("Invalid UUID string: " + str, e);
|
||||
}
|
||||
} else {
|
||||
throw new ItemStatDataLoadException("Invalid UUID value: " + value);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new ItemStatDataLoadException(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
26
src/main/java/com/io/yutian/elementoriginlib/util/Util.java
Normal file
26
src/main/java/com/io/yutian/elementoriginlib/util/Util.java
Normal file
|
@ -0,0 +1,26 @@
|
|||
package com.io.yutian.elementoriginlib.util;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class Util {
|
||||
|
||||
public static <T> Predicate<T> allOf(List<? extends Predicate<T>> predicates) {
|
||||
List<Predicate<T>> list = List.copyOf(predicates);
|
||||
|
||||
return switch (list.size()) {
|
||||
case 0 -> object -> true;
|
||||
case 1 -> list.get(0);
|
||||
case 2 -> list.get(0).and(list.get(1));
|
||||
default -> object -> {
|
||||
for (Predicate<T> predicate : list) {
|
||||
if (!predicate.test(object)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
}
|
0
src/main/resources/mangodb.yml
Normal file
0
src/main/resources/mangodb.yml
Normal file
|
@ -5,4 +5,4 @@ api-version: '1.20'
|
|||
authors: [ SuperYuTian ]
|
||||
commands:
|
||||
elementoriginlib:
|
||||
aliases: [ eol ]
|
||||
aliases: [ eolib ]
|
Loading…
Reference in New Issue
Block a user