v1.0
This commit is contained in:
commit
b324ce05c6
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
/AuLib.iml
|
||||
.idea
|
||||
target
|
||||
/.idea/
|
89
pom.xml
Normal file
89
pom.xml
Normal file
|
@ -0,0 +1,89 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>com.io.yutian.aulib</groupId>
|
||||
<artifactId>AuLib</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>papermc-repo</id>
|
||||
<url>https://repo.papermc.io/repository/maven-public/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>sonatype</id>
|
||||
<url>https://oss.sonatype.org/content/groups/public/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>public</id>
|
||||
<url>https://repo.aurora-pixels.com/repository/public/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>public-rpg</id>
|
||||
<url>https://repo.aurora-pixels.com/repository/public-rpg/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>spigotmc-repo</id>
|
||||
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>rapture-snapshots</id>
|
||||
<url>https://repo.rapture.pw/repository/maven-snapshots/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>io.papermc.paper</groupId>
|
||||
<artifactId>paper-api</artifactId>
|
||||
<version>1.18.2-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.io.yutian.pixelpaper</groupId>
|
||||
<artifactId>pixelpaper-api</artifactId>
|
||||
<version>1.18.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot</artifactId>
|
||||
<version>1.18.2</version>
|
||||
<classifier>nms</classifier>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.mojang</groupId>
|
||||
<artifactId>authlib</artifactId>
|
||||
<version>3.3.39</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.mojang</groupId>
|
||||
<artifactId>brigadier</artifactId>
|
||||
<version>1.0.18</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.mojang</groupId>
|
||||
<artifactId>datafixerupper</artifactId>
|
||||
<version>4.1.27</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-compress</artifactId>
|
||||
<version>1.26.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.luben</groupId>
|
||||
<artifactId>zstd-jni</artifactId>
|
||||
<version>1.5.6-3</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
29
src/main/java/com/io/yutian/aulib/AuLib.java
Normal file
29
src/main/java/com/io/yutian/aulib/AuLib.java
Normal file
|
@ -0,0 +1,29 @@
|
|||
package com.io.yutian.aulib;
|
||||
|
||||
import com.io.yutian.aulib.lang.Lang;
|
||||
import com.io.yutian.aulib.listener.GuiHandlerListener;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
public class AuLib extends JavaPlugin {
|
||||
|
||||
private static AuLib instance;
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
instance = this;
|
||||
|
||||
registerListeners();
|
||||
|
||||
Lang.registerLangFile(this);
|
||||
Lang.reload(this);
|
||||
}
|
||||
|
||||
private void registerListeners() {
|
||||
new GuiHandlerListener(this);
|
||||
}
|
||||
|
||||
public static AuLib inst() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
}
|
8
src/main/java/com/io/yutian/aulib/command/Command.java
Normal file
8
src/main/java/com/io/yutian/aulib/command/Command.java
Normal file
|
@ -0,0 +1,8 @@
|
|||
package com.io.yutian.aulib.command;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Command<S extends CommandContext> {
|
||||
|
||||
void run(S context);
|
||||
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
package com.io.yutian.aulib.command;
|
||||
|
||||
import com.io.yutian.aulib.command.argument.ArgumentValue;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class CommandContext {
|
||||
|
||||
private String command;
|
||||
private String label;
|
||||
private CommandSender sender;
|
||||
private Map<String, ArgumentValue> argumentsValues;
|
||||
|
||||
public CommandContext(String command, String label, CommandSender sender, Map<String, ArgumentValue> argumentsValues) {
|
||||
this.command = command;
|
||||
this.label = label;
|
||||
this.sender = sender;
|
||||
this.argumentsValues = argumentsValues;
|
||||
}
|
||||
|
||||
public String getCommand() {
|
||||
return command;
|
||||
}
|
||||
|
||||
public String getLabel() {
|
||||
return label;
|
||||
}
|
||||
|
||||
public CommandSender getSender() {
|
||||
return sender;
|
||||
}
|
||||
|
||||
public ArgumentValue getArgumentsValue(String key) {
|
||||
return argumentsValues.getOrDefault(key, new ArgumentValue(null));
|
||||
}
|
||||
|
||||
}
|
91
src/main/java/com/io/yutian/aulib/command/CommandNode.java
Normal file
91
src/main/java/com/io/yutian/aulib/command/CommandNode.java
Normal file
|
@ -0,0 +1,91 @@
|
|||
package com.io.yutian.aulib.command;
|
||||
|
||||
import com.io.yutian.aulib.command.argument.Argument;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class CommandNode {
|
||||
|
||||
private String name;
|
||||
|
||||
private List<CommandNode> childrens = new ArrayList<>();
|
||||
private List<Argument> arguments = new ArrayList<>();
|
||||
|
||||
private List<String> alias = new ArrayList<>();
|
||||
|
||||
private Predicate<CommandSender> commandSenderPredicate = (commandSender -> true);
|
||||
private Command command;
|
||||
|
||||
public CommandNode(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public CommandNode(String name, String[] alias) {
|
||||
this.name = name;
|
||||
this.alias = Arrays.asList(alias);
|
||||
}
|
||||
|
||||
public CommandNode(String name, List<String> alias) {
|
||||
this.name = name;
|
||||
this.alias = alias;
|
||||
}
|
||||
|
||||
public CommandNode permission(Predicate<CommandSender> commandSenderPredicate) {
|
||||
this.commandSenderPredicate = commandSenderPredicate;
|
||||
return this;
|
||||
}
|
||||
|
||||
public List<String> getAlias() {
|
||||
return alias;
|
||||
}
|
||||
|
||||
public CommandNode setAlias(List<String> alias) {
|
||||
this.alias = alias;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandNode addAilas(String alias) {
|
||||
this.alias.add(alias);
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandNode addArgument(Argument argument) {
|
||||
arguments.add(argument);
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandNode addChildren(CommandNode commandNode) {
|
||||
this.childrens.add(commandNode);
|
||||
return this;
|
||||
}
|
||||
|
||||
public List<CommandNode> getChildrens() {
|
||||
return childrens;
|
||||
}
|
||||
|
||||
public List<Argument> getArguments() {
|
||||
return arguments;
|
||||
}
|
||||
|
||||
public CommandNode executes(Command command) {
|
||||
this.command = command;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Command getCommand() {
|
||||
return command;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public static CommandNode node(String name) {
|
||||
return new CommandNode(name);
|
||||
}
|
||||
|
||||
}
|
11
src/main/java/com/io/yutian/aulib/command/IAlias.java
Normal file
11
src/main/java/com/io/yutian/aulib/command/IAlias.java
Normal file
|
@ -0,0 +1,11 @@
|
|||
package com.io.yutian.aulib.command;
|
||||
|
||||
public interface IAlias {
|
||||
|
||||
default boolean inMainCommand() {
|
||||
return true;
|
||||
}
|
||||
|
||||
String[] getAlias();
|
||||
|
||||
}
|
67
src/main/java/com/io/yutian/aulib/command/ICommand.java
Normal file
67
src/main/java/com/io/yutian/aulib/command/ICommand.java
Normal file
|
@ -0,0 +1,67 @@
|
|||
package com.io.yutian.aulib.command;
|
||||
|
||||
import com.io.yutian.aulib.command.argument.Argument;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class ICommand {
|
||||
|
||||
private String name;
|
||||
private String description;
|
||||
|
||||
private List<CommandNode> commandNodes = new ArrayList<>();
|
||||
private List<Argument> arguments = new ArrayList<>();
|
||||
|
||||
public ICommand(String name) {
|
||||
this(name, null);
|
||||
}
|
||||
|
||||
public ICommand(String name, String description) {
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public void executes(CommandContext commandContext) {
|
||||
}
|
||||
|
||||
public boolean emptyExecutes(CommandSender commandSender) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean hasPermission(CommandSender sender) {
|
||||
return sender.isOp() || sender.hasPermission(getPermissionPrefix()+"."+name);
|
||||
}
|
||||
|
||||
public String getPermissionPrefix() {
|
||||
return "command."+name;
|
||||
}
|
||||
|
||||
public ICommand addArgument(Argument argument) {
|
||||
arguments.add(argument);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ICommand addCommandNode(CommandNode commandNode) {
|
||||
this.commandNodes.add(commandNode);
|
||||
return this;
|
||||
}
|
||||
|
||||
public List<CommandNode> getCommandNodes() {
|
||||
return commandNodes;
|
||||
}
|
||||
|
||||
public List<Argument> getArguments() {
|
||||
return arguments;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package com.io.yutian.aulib.command;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ICommandManager {
|
||||
|
||||
String getName();
|
||||
|
||||
List<ICommand> getCommands();
|
||||
|
||||
}
|
29
src/main/java/com/io/yutian/aulib/command/ITabCompleter.java
Normal file
29
src/main/java/com/io/yutian/aulib/command/ITabCompleter.java
Normal file
|
@ -0,0 +1,29 @@
|
|||
package com.io.yutian.aulib.command;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public interface ITabCompleter {
|
||||
|
||||
List<String> onTabComplete(CommandSender commandSender, String[] args, int index, String lastArg);
|
||||
|
||||
static List<String> getPlayerList(String arg) {
|
||||
List<String> list = new ArrayList<>();
|
||||
for (Player player : Bukkit.getOnlinePlayers()) {
|
||||
String name = player.getName();
|
||||
if (arg != null && !arg.trim().equalsIgnoreCase("")) {
|
||||
if (name.toLowerCase().startsWith(arg.toLowerCase())) {
|
||||
list.add(name);
|
||||
}
|
||||
} else {
|
||||
list.add(name);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
package com.io.yutian.aulib.command;
|
||||
|
||||
import com.io.yutian.aulib.command.handler.CommandHandler;
|
||||
import com.io.yutian.aulib.command.list.CommandHelp;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class SimpleCommandManager implements ICommandManager {
|
||||
|
||||
private final String name;
|
||||
|
||||
@NotNull
|
||||
private List<ICommand> commands;
|
||||
|
||||
public SimpleCommandManager(String name) {
|
||||
this(name, new ArrayList<>());
|
||||
}
|
||||
|
||||
public SimpleCommandManager(String name, @NotNull List<ICommand> commands) {
|
||||
this.name = name;
|
||||
this.commands = commands;
|
||||
register(new CommandHelp(this));
|
||||
}
|
||||
|
||||
public void register(@NotNull ICommand command) {
|
||||
if (command == null) {
|
||||
return;
|
||||
}
|
||||
commands.add(command);
|
||||
}
|
||||
|
||||
public void registerBukkitCommand(@NotNull Plugin plugin, String commandName) {
|
||||
Bukkit.getPluginCommand(commandName).setExecutor(new CommandHandler(plugin, this));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<ICommand> getCommands() {
|
||||
return commands;
|
||||
}
|
||||
|
||||
}
|
10
src/main/java/com/io/yutian/aulib/command/Suggest.java
Normal file
10
src/main/java/com/io/yutian/aulib/command/Suggest.java
Normal file
|
@ -0,0 +1,10 @@
|
|||
package com.io.yutian.aulib.command;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Suggest {
|
||||
|
||||
List<String> getSuggest();
|
||||
|
||||
}
|
28
src/main/java/com/io/yutian/aulib/command/Suggests.java
Normal file
28
src/main/java/com/io/yutian/aulib/command/Suggests.java
Normal file
|
@ -0,0 +1,28 @@
|
|||
package com.io.yutian.aulib.command;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
public class Suggests {
|
||||
|
||||
public static final Suggest WORLD_LIST = ()->{
|
||||
List<String> list = new LinkedList<>();
|
||||
for (World world : Bukkit.getWorlds()) {
|
||||
list.add(world.getName());
|
||||
}
|
||||
return list;
|
||||
};
|
||||
|
||||
public static final Suggest PLAYER_LIST = ()->{
|
||||
List<String> list = new LinkedList<>();
|
||||
for (Player player : Bukkit.getOnlinePlayers()) {
|
||||
list.add(player.getName());
|
||||
}
|
||||
return list;
|
||||
};
|
||||
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
package com.io.yutian.aulib.command.argument;
|
||||
|
||||
import com.io.yutian.aulib.command.Suggest;
|
||||
|
||||
public class Argument {
|
||||
|
||||
private String name;
|
||||
|
||||
private ArgumentType argumentsType;
|
||||
|
||||
private Suggest suggest;
|
||||
|
||||
private boolean optional = false;
|
||||
private Object defaultValue = null;
|
||||
|
||||
public Argument(String name, ArgumentType argumentsType) {
|
||||
this.name = name;
|
||||
this.argumentsType = argumentsType;
|
||||
}
|
||||
|
||||
public Argument optional(Object defaultValue) {
|
||||
optional = true;
|
||||
this.defaultValue = defaultValue;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public ArgumentType getArgumentsType() {
|
||||
return argumentsType;
|
||||
}
|
||||
|
||||
public boolean isOptional() {
|
||||
return optional;
|
||||
}
|
||||
|
||||
public Object getDefaultValue() {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
public Argument suggest(Suggest suggest) {
|
||||
this.suggest = suggest;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Suggest getSuggest() {
|
||||
return suggest;
|
||||
}
|
||||
|
||||
public static Argument argument(String name, ArgumentType type) {
|
||||
return new Argument(name, type);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
package com.io.yutian.aulib.command.argument;
|
||||
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class ArgumentType<T> {
|
||||
|
||||
private final String name;
|
||||
|
||||
private Predicate<String> predicate;
|
||||
private Function<String, T> function;
|
||||
|
||||
public ArgumentType(String name, Predicate<String> predicate, Function<String, T> function) {
|
||||
this.name = name;
|
||||
this.predicate = predicate;
|
||||
this.function = function;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public boolean test(String string) {
|
||||
return predicate.test(string);
|
||||
}
|
||||
|
||||
public T get(String t) {
|
||||
return function.apply(t);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package com.io.yutian.aulib.command.argument;
|
||||
|
||||
import com.io.yutian.aulib.util.StringUtil;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class ArgumentTypes {
|
||||
|
||||
public static final ArgumentType<String> STRING = new ArgumentType<>("string", (s) -> true, (s) -> s);
|
||||
|
||||
public static final ArgumentType<Integer> INTEGER = new ArgumentType<>("integer", StringUtil::isInt, Integer::parseInt);
|
||||
|
||||
public static final ArgumentType<Double> DOUBLE = new ArgumentType<>("double", StringUtil::isDouble, Double::parseDouble);
|
||||
|
||||
public static final ArgumentType<UUID> UUID = new ArgumentType<>("uuid", StringUtil::isUUID, java.util.UUID::fromString);
|
||||
|
||||
public static final ArgumentType<Boolean> BOOLEAN = new ArgumentType<>("boolean", StringUtil::isBoolean, Boolean::parseBoolean);
|
||||
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
package com.io.yutian.aulib.command.argument;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
public class ArgumentValue {
|
||||
|
||||
private static final Map<Class<?>, Class<?>> PRIMITIVE_TO_WRAPPER = new HashMap<>();
|
||||
|
||||
static {
|
||||
PRIMITIVE_TO_WRAPPER.put(boolean.class, Boolean.class);
|
||||
PRIMITIVE_TO_WRAPPER.put(byte.class, Byte.class);
|
||||
PRIMITIVE_TO_WRAPPER.put(short.class, Short.class);
|
||||
PRIMITIVE_TO_WRAPPER.put(char.class, Character.class);
|
||||
PRIMITIVE_TO_WRAPPER.put(int.class, Integer.class);
|
||||
PRIMITIVE_TO_WRAPPER.put(long.class, Long.class);
|
||||
PRIMITIVE_TO_WRAPPER.put(float.class, Float.class);
|
||||
PRIMITIVE_TO_WRAPPER.put(double.class, Double.class);
|
||||
}
|
||||
|
||||
private Object value;
|
||||
|
||||
public ArgumentValue(Object value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public Object getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public <V> V get(Class<V> clazz) {
|
||||
if (PRIMITIVE_TO_WRAPPER.getOrDefault(clazz, clazz).isAssignableFrom(value.getClass())) {
|
||||
return (V) value;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getString() {
|
||||
return (String) value;
|
||||
}
|
||||
|
||||
public int getInt() {
|
||||
return (Integer) value;
|
||||
}
|
||||
|
||||
public double getDouble() {
|
||||
return (Double) value;
|
||||
}
|
||||
|
||||
public boolean getBoolean() {
|
||||
return (Boolean) value;
|
||||
}
|
||||
|
||||
public UUID getUUID() {
|
||||
return (UUID) value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ArgumentValue{" +
|
||||
"value=" + value +
|
||||
'}';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,341 @@
|
|||
package com.io.yutian.aulib.command.handler;
|
||||
|
||||
import com.io.yutian.aulib.command.*;
|
||||
import com.io.yutian.aulib.command.argument.Argument;
|
||||
import com.io.yutian.aulib.command.argument.ArgumentValue;
|
||||
import com.io.yutian.aulib.lang.Lang;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.TabCompleter;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class CommandHandler implements CommandExecutor, TabCompleter {
|
||||
|
||||
private ICommandManager commandManager;
|
||||
|
||||
public CommandHandler(Plugin plugin, ICommandManager commandManager) {
|
||||
this.commandManager = commandManager;
|
||||
}
|
||||
|
||||
public void execute(CommandSender sender, String label, String[] args) {
|
||||
if (args.length == 0) {
|
||||
execute(sender, label, new String[]{"help", "1"});
|
||||
return;
|
||||
}
|
||||
List<ICommand> commands = commandManager.getCommands();
|
||||
String command = args[0];
|
||||
Stream<ICommand> stream = commands.stream().filter((c) -> c.getName().equalsIgnoreCase(command));
|
||||
Optional<ICommand> optional = stream.findFirst();
|
||||
if (!optional.isPresent()) {
|
||||
sender.sendMessage(Lang.get("command-unknown", command));
|
||||
return;
|
||||
}
|
||||
ICommand iCommand = optional.get();
|
||||
if (!iCommand.hasPermission(sender)) {
|
||||
sender.sendMessage(Lang.get("command-no-permission"));
|
||||
return;
|
||||
}
|
||||
List<CommandNode> commandNodes = iCommand.getCommandNodes();
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
stringBuilder.append(args[i]);
|
||||
if (i < args.length - 1) {
|
||||
stringBuilder.append(" ");
|
||||
}
|
||||
}
|
||||
String commandString = stringBuilder.toString();
|
||||
if (commandNodes.size() == 0) {
|
||||
Map<String, ArgumentValue> map = new HashMap<>();
|
||||
if (iCommand.getArguments().size() > 0) {
|
||||
int argSize = args.length - 1;
|
||||
List<Argument> arguments = iCommand.getArguments();
|
||||
int k = 0;
|
||||
if (arguments.get(arguments.size()-1).isOptional()) {
|
||||
k++;
|
||||
}
|
||||
if (argSize < arguments.size()-k) {
|
||||
sender.sendMessage(Lang.get("command-short-arg"));
|
||||
return;
|
||||
}
|
||||
for (int l = 0; l < arguments.size(); l++) {
|
||||
Argument a = arguments.get(l);
|
||||
int index = l + 1;
|
||||
if (index >= args.length) {
|
||||
break;
|
||||
}
|
||||
String arg = args[index];
|
||||
if (!a.getArgumentsType().test(arg)) {
|
||||
sender.sendMessage(Lang.get("command-unknown-arg", index+1, arg));
|
||||
return;
|
||||
}
|
||||
}
|
||||
map = parseArgumentValue(sender, arguments, args, 0);
|
||||
}
|
||||
iCommand.executes(new CommandContext(commandString, label, sender, map));
|
||||
return;
|
||||
}
|
||||
|
||||
int nodeSize = args.length - 1;
|
||||
|
||||
if (commandNodes.size() > 0 && nodeSize == 0) {
|
||||
if (!iCommand.emptyExecutes(sender)) {
|
||||
sender.sendMessage(Lang.get("command-short-arg"));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
String mainNode = args[1];
|
||||
Stream<CommandNode> nodeStream = commandNodes.stream().filter((n) -> n.getName().equalsIgnoreCase(mainNode) || n.getAlias().contains(mainNode));
|
||||
Optional<CommandNode> nodeOptional = nodeStream.findFirst();
|
||||
if (!nodeOptional.isPresent()) {
|
||||
sender.sendMessage(Lang.get("command-unknown-arg", 2, mainNode));
|
||||
return;
|
||||
}
|
||||
CommandNode node = nodeOptional.get();
|
||||
|
||||
if (node.getChildrens().size() > 0) {
|
||||
checkClidren(commandString, label, sender, 1, args, node);
|
||||
} else {
|
||||
if (node.getCommand() != null) {
|
||||
Map<String, ArgumentValue> map = new HashMap<>();
|
||||
if (node.getArguments().size() > 0) {
|
||||
int argSize = args.length - 2;
|
||||
List<Argument> arguments = node.getArguments();
|
||||
int k = 0;
|
||||
if (arguments.get(arguments.size()-1).isOptional()) {
|
||||
k++;
|
||||
}
|
||||
if (argSize < arguments.size()-k) {
|
||||
sender.sendMessage(Lang.get("command-short-arg"));
|
||||
return;
|
||||
}
|
||||
for (int l = 0; l < arguments.size(); l++) {
|
||||
Argument a = arguments.get(l);
|
||||
int index = l + 1;
|
||||
if (index >= args.length) {
|
||||
break;
|
||||
}
|
||||
if (index+1 >= args.length) {
|
||||
break;
|
||||
}
|
||||
String arg = args[index+1];
|
||||
if (!a.getArgumentsType().test(arg)) {
|
||||
sender.sendMessage(Lang.get("command-error-arg", index+1, arg));
|
||||
return;
|
||||
}
|
||||
}
|
||||
map = parseArgumentValue(sender, node.getArguments(), args, 1);
|
||||
}
|
||||
node.getCommand().run(new CommandContext(commandString, label, sender, map));
|
||||
} else {
|
||||
sender.sendMessage(Lang.get("command-unknown-arg", 3, mainNode));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private Map<String, ArgumentValue> parseArgumentValue(CommandSender commandSender, List<Argument> argumentList, String[] args, int i) {
|
||||
Map<String, ArgumentValue> map = new HashMap<>();
|
||||
List<Argument> arguments = argumentList;
|
||||
for (int l = 0; l < arguments.size(); l++) {
|
||||
Argument a = arguments.get(l);
|
||||
if (i+1+l >= args.length) {
|
||||
if (a.isOptional()) {
|
||||
map.put(a.getName(), new ArgumentValue(a.getDefaultValue()));
|
||||
}
|
||||
return map;
|
||||
}
|
||||
String arg = args[i+1+l];
|
||||
if (!a.getArgumentsType().test(arg)) {
|
||||
continue;
|
||||
}
|
||||
ArgumentValue argumentValue = new ArgumentValue(a.getArgumentsType().get(arg));
|
||||
map.put(a.getName(), argumentValue);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
private void checkClidren(String commandString, String label, CommandSender sender, int i, String[] args, CommandNode node) {
|
||||
i++;
|
||||
if (i >= args.length) {
|
||||
if (node.getCommand() == null) {
|
||||
sender.sendMessage(Lang.get("command-short-arg"));
|
||||
} else {
|
||||
node.getCommand().run(new CommandContext(commandString, label, sender, new HashMap<>()));
|
||||
}
|
||||
return;
|
||||
}
|
||||
String s = args[i];
|
||||
Stream<CommandNode> nodeStream = node.getChildrens().stream().filter((n) -> n.getName().equalsIgnoreCase(s) || n.getAlias().contains(s));
|
||||
Optional<CommandNode> nodeOptional = nodeStream.findFirst();
|
||||
if (!nodeOptional.isPresent()) {
|
||||
sender.sendMessage(Lang.get("command-unknown-arg", i+1, s));
|
||||
return;
|
||||
}
|
||||
CommandNode node1 = nodeOptional.get();
|
||||
|
||||
if (node1.getChildrens().size() > 0) {
|
||||
checkClidren(commandString, label, sender, i, args, node1);
|
||||
} else {
|
||||
if (node1.getCommand() != null) {
|
||||
Map<String, ArgumentValue> map = new HashMap<>();
|
||||
if (node1.getArguments().size() > 0) {
|
||||
int argSize = args.length - i - 1;
|
||||
List<Argument> arguments = node1.getArguments();
|
||||
int k = 0;
|
||||
if (arguments.get(arguments.size()-1).isOptional()) {
|
||||
k++;
|
||||
}
|
||||
if (argSize < arguments.size()-k) {
|
||||
sender.sendMessage(Lang.get("command-short-arg"));
|
||||
return;
|
||||
}
|
||||
for (int l = 0; l < arguments.size(); l++) {
|
||||
Argument a = arguments.get(l);
|
||||
int index = i + l + 1;
|
||||
if (index >= args.length) {
|
||||
break;
|
||||
}
|
||||
String arg = args[index];
|
||||
if (!a.getArgumentsType().test(arg)) {
|
||||
sender.sendMessage(Lang.get("command-unknown-arg", index+1, arg));
|
||||
return;
|
||||
}
|
||||
}
|
||||
map = parseArgumentValue(sender, node1.getArguments(), args, i);
|
||||
}
|
||||
node1.getCommand().run(new CommandContext(commandString, label, sender, map));
|
||||
} else {
|
||||
sender.sendMessage(Lang.get("command-unknown-arg", i+1, s));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
execute(sender, label, args);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
|
||||
List<String> list = new ArrayList<>();
|
||||
int index = args.length;
|
||||
String arg = args[index-1];
|
||||
List<ICommand> commands = commandManager.getCommands();
|
||||
if (index == 1) {
|
||||
List<ICommand> commandList = commands.stream().filter((c)->c.getName().startsWith(arg)).collect(Collectors.toList());
|
||||
if (commandList.size() > 0) {
|
||||
commandList.forEach(c-> {
|
||||
if (c.hasPermission(sender)) {
|
||||
list.add(c.getName());
|
||||
}
|
||||
});
|
||||
return list;
|
||||
}
|
||||
commandList = commands.stream().filter((c)->c.getName().contains(arg)).collect(Collectors.toList());
|
||||
if (commandList.size() > 0) {
|
||||
commandList.forEach(c-> {
|
||||
if (c.hasPermission(sender)) {
|
||||
list.add(c.getName());
|
||||
}
|
||||
});
|
||||
return list;
|
||||
}
|
||||
} else {
|
||||
Optional<ICommand> iCommandOptional = commands.stream().filter((c)->c.getName().equalsIgnoreCase(args[0])).findFirst();
|
||||
if (!iCommandOptional.isPresent()) {
|
||||
return list;
|
||||
}
|
||||
ICommand iCommand = iCommandOptional.get();
|
||||
if (!iCommand.hasPermission(sender)) {
|
||||
return list;
|
||||
}
|
||||
if (iCommand instanceof ITabCompleter) {
|
||||
ITabCompleter tabCompleter = (ITabCompleter) iCommand;
|
||||
return tabCompleter.onTabComplete(sender, args, index-2, arg);
|
||||
} else {
|
||||
Map<Integer, List<String>> map = new HashMap<>();
|
||||
if (iCommand.getCommandNodes().size() > 0) {
|
||||
List<String> list1 = new ArrayList<>();
|
||||
for (CommandNode node : iCommand.getCommandNodes()) {
|
||||
list1.add(node.getName());
|
||||
list1.addAll(node.getAlias());
|
||||
if (index >= 2) {
|
||||
if (!node.getName().equalsIgnoreCase(args[1])) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (node.getChildrens().size() > 0) {
|
||||
getTabComplete(node, 2, map);
|
||||
} else if (node.getArguments().size() > 0) {
|
||||
List<Argument> arguments = node.getArguments();
|
||||
for (int l = 0; l < arguments.size(); l++) {
|
||||
Argument argument = arguments.get(l);
|
||||
if (argument.getSuggest() != null) {
|
||||
map.put(2+l+1, argument.getSuggest().getSuggest());
|
||||
continue;
|
||||
}
|
||||
map.put(2+l+1, Arrays.asList("<"+argument.getName()+">"));
|
||||
}
|
||||
}
|
||||
}
|
||||
map.put(2, list1);
|
||||
return preseSuggest(map.getOrDefault(index, list), arg);
|
||||
} else if (iCommand.getArguments().size() > 0) {
|
||||
List<Argument> arguments = iCommand.getArguments();
|
||||
for (int l = 0; l < arguments.size(); l++) {
|
||||
Argument argument = arguments.get(l);
|
||||
if (argument.getSuggest() != null) {
|
||||
map.put(1+l+1, argument.getSuggest().getSuggest());
|
||||
continue;
|
||||
}
|
||||
map.put(1+l+1, Arrays.asList("<"+argument.getName()+">"));
|
||||
}
|
||||
return preseSuggest(map.getOrDefault(index, list), arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
return preseSuggest(list, arg);
|
||||
}
|
||||
|
||||
public static List<String> preseSuggest(List<String> list, String arg) {
|
||||
List<String> newList = new ArrayList<>();
|
||||
List<String> list1 = list.stream().filter((c)->c.startsWith(arg)||c.toLowerCase().startsWith(arg.toLowerCase())).collect(Collectors.toList());
|
||||
List<String> list2 = list.stream().filter((c)->c.contains(arg)||c.toLowerCase().contains(arg.toLowerCase())).collect(Collectors.toList());
|
||||
List<String> list3 = list.stream().filter((c)->c.equalsIgnoreCase(arg)|| c.equalsIgnoreCase(arg)).collect(Collectors.toList());
|
||||
newList.addAll(list1);
|
||||
newList.addAll(list2);
|
||||
newList.addAll(list3);
|
||||
return newList;
|
||||
}
|
||||
|
||||
private void getTabComplete(CommandNode node, int i, Map<Integer, List<String>> map) {
|
||||
i++;
|
||||
List<String> list = map.getOrDefault(i, new ArrayList<>());
|
||||
for (CommandNode c : node.getChildrens()) {
|
||||
list.add(c.getName());
|
||||
if (c.getChildrens().size() > 0) {
|
||||
getTabComplete(c, i, map);
|
||||
} else if (c.getArguments().size() > 0) {
|
||||
List<Argument> arguments = c.getArguments();
|
||||
for (int l = 0; l < arguments.size(); l++) {
|
||||
Argument argument = arguments.get(l);
|
||||
if (argument.getSuggest() != null) {
|
||||
map.put(i+l+1, argument.getSuggest().getSuggest());
|
||||
continue;
|
||||
}
|
||||
map.put(i+l+1, Arrays.asList("<"+argument.getName()+">"));
|
||||
}
|
||||
}
|
||||
}
|
||||
map.put(i, list);
|
||||
}
|
||||
|
||||
}
|
117
src/main/java/com/io/yutian/aulib/command/list/CommandHelp.java
Normal file
117
src/main/java/com/io/yutian/aulib/command/list/CommandHelp.java
Normal file
|
@ -0,0 +1,117 @@
|
|||
package com.io.yutian.aulib.command.list;
|
||||
|
||||
import com.io.yutian.aulib.command.CommandContext;
|
||||
import com.io.yutian.aulib.command.CommandNode;
|
||||
import com.io.yutian.aulib.command.ICommand;
|
||||
import com.io.yutian.aulib.command.ICommandManager;
|
||||
import com.io.yutian.aulib.command.argument.Argument;
|
||||
import com.io.yutian.aulib.command.argument.ArgumentTypes;
|
||||
import com.io.yutian.aulib.lang.Lang;
|
||||
import com.io.yutian.aulib.util.ComponentBuilder;
|
||||
import com.io.yutian.aulib.list.PageList;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.event.ClickEvent;
|
||||
import net.kyori.adventure.text.event.HoverEvent;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class CommandHelp extends ICommand {
|
||||
|
||||
private ICommandManager commandManager;
|
||||
@Nullable
|
||||
private String alias;
|
||||
|
||||
public CommandHelp(ICommandManager commandManager) {
|
||||
this(commandManager, null);
|
||||
}
|
||||
|
||||
public CommandHelp(ICommandManager commandManager, String alias) {
|
||||
super("help");
|
||||
this.commandManager = commandManager;
|
||||
this.alias = alias;
|
||||
addArgument(Argument.argument("page", ArgumentTypes.INTEGER).optional(1));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(CommandSender sender) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executes(CommandContext commandContext) {
|
||||
String commandAlias = alias != null ? alias : commandContext.getLabel();
|
||||
CommandSender sender = commandContext.getSender();
|
||||
int page = commandContext.getArgumentsValue("page").getInt();
|
||||
if (page <= 0) {
|
||||
sender.sendMessage(Lang.get("command.help.page-error"));
|
||||
return;
|
||||
}
|
||||
List<ICommand> commands = commandManager.getCommands();
|
||||
Stream<ICommand> stream = commands.stream().filter((c) -> c.hasPermission(sender));
|
||||
List<ICommand> list = stream.collect(Collectors.toList());
|
||||
PageList<ICommand> pageList = new PageList<>(list, 8);
|
||||
if (page > pageList.size()) {
|
||||
sender.sendMessage(Lang.get("command.help.page-error"));
|
||||
return;
|
||||
}
|
||||
sender.sendMessage(" ");
|
||||
List<ICommand> commandList = pageList.getList(page);
|
||||
sender.sendMessage("§7======[ §e§l"+commandManager.getName()+" §7]======");
|
||||
for (ICommand command : commandList) {
|
||||
StringBuilder stringBuilder = new StringBuilder("§6/"+commandAlias+" "+command.getName());
|
||||
stringBuilder.append("§f");
|
||||
if (command.getCommandNodes().size() > 0) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(" [");
|
||||
int i = 0;
|
||||
for (CommandNode node : command.getCommandNodes()) {
|
||||
sb.append(node.getName());
|
||||
if (i + 1 < command.getCommandNodes().size()) {
|
||||
sb.append("/");
|
||||
}
|
||||
i++;
|
||||
}
|
||||
sb.append("]");
|
||||
stringBuilder.append(sb);
|
||||
} else {
|
||||
for (Argument argument : command.getArguments()) {
|
||||
stringBuilder.append(" ");
|
||||
stringBuilder.append("<"+argument.getName()+">");
|
||||
}
|
||||
}
|
||||
if (command.getDescription() != null) {
|
||||
stringBuilder.append(" ");
|
||||
stringBuilder.append("§7- §f"+command.getDescription());
|
||||
}
|
||||
sender.sendMessage(stringBuilder.toString());
|
||||
}
|
||||
ComponentBuilder componentBuilder = new ComponentBuilder();
|
||||
boolean hasUpPage = page > 1;
|
||||
boolean hasNextPage = page < pageList.size();
|
||||
componentBuilder.add("§7=====");
|
||||
if (hasUpPage) {
|
||||
componentBuilder.add(" §7["+getColor(true)+"◀§7] ", ClickEvent.clickEvent(ClickEvent.Action.RUN_COMMAND, "/"+commandAlias+" help "+(page-1)), HoverEvent.hoverEvent(HoverEvent.Action.SHOW_TEXT, Component.text("§f上一页")));
|
||||
} else {
|
||||
componentBuilder.add(" §7["+getColor(false)+"◀§7] ");
|
||||
}
|
||||
componentBuilder.add("§7====");
|
||||
componentBuilder.add("(§a"+page+"§f/§e"+pageList.size()+"§7)");
|
||||
componentBuilder.add("§7====");
|
||||
if (hasNextPage) {
|
||||
componentBuilder.add(" §7["+getColor(true)+"▶§7] ", ClickEvent.clickEvent(ClickEvent.Action.RUN_COMMAND, "/"+commandAlias+" help "+(page+1)), HoverEvent.hoverEvent(HoverEvent.Action.SHOW_TEXT, Component.text("§f下一页")));
|
||||
} else {
|
||||
componentBuilder.add(" §7["+getColor(false)+"▶§7] ");
|
||||
}
|
||||
componentBuilder.add("§7=====");
|
||||
sender.sendMessage(componentBuilder.build());
|
||||
}
|
||||
|
||||
private String getColor(boolean hasPage) {
|
||||
return hasPage ? "§a" : "§c";
|
||||
}
|
||||
|
||||
}
|
132
src/main/java/com/io/yutian/aulib/gui/Gui.java
Normal file
132
src/main/java/com/io/yutian/aulib/gui/Gui.java
Normal file
|
@ -0,0 +1,132 @@
|
|||
package com.io.yutian.aulib.gui;
|
||||
|
||||
import com.io.yutian.aulib.AuLib;
|
||||
import com.io.yutian.aulib.gui.button.Button;
|
||||
import com.io.yutian.aulib.gui.button.ClickType;
|
||||
import com.io.yutian.aulib.gui.button.ItemButton;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.InventoryAction;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class Gui extends IGui {
|
||||
|
||||
private Map<Integer, Button> buttons = new HashMap<>();
|
||||
|
||||
public Gui(Player player, String title, int size) {
|
||||
super(player, title, size);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handler(Player player, int slot, InventoryClickEvent event) {
|
||||
if (buttons.containsKey(slot)) {
|
||||
Button button = buttons.get(slot);
|
||||
if (button == null) {
|
||||
if (slot < inventory.getSize()) {
|
||||
event.setCancelled(true);
|
||||
} else {
|
||||
if (event.getAction().equals(InventoryAction.MOVE_TO_OTHER_INVENTORY)) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
event.setCancelled(true);
|
||||
clickButton(event, slot, button);
|
||||
if (button.isPlaySound()) {
|
||||
player.playSound(player.getLocation(), Sound.UI_BUTTON_CLICK, 1.0f, 1.0f);
|
||||
}
|
||||
InventoryAction action = event.getAction();
|
||||
ClickType clickType = ClickType.LEFT_CLICK;
|
||||
if (action.equals(InventoryAction.PICKUP_ALL)) {
|
||||
clickType = ClickType.LEFT_CLICK;
|
||||
} else if (action.equals(InventoryAction.PICKUP_HALF)) {
|
||||
clickType = ClickType.RIGHT_CLICK;
|
||||
} else if (action.equals(InventoryAction.MOVE_TO_OTHER_INVENTORY)) {
|
||||
clickType = ClickType.SHIFT_CLICK;
|
||||
}
|
||||
if (button.getClickConsumer() != null) {
|
||||
button.getClickConsumer().accept(player, clickType);
|
||||
}
|
||||
} else {
|
||||
if (slot < inventory.getSize()) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void addButton(int index, Button button) {
|
||||
buttons.put(index, button);
|
||||
}
|
||||
|
||||
public Button getButton(int index) {
|
||||
return buttons.getOrDefault(index, null);
|
||||
}
|
||||
|
||||
public final void initButton(int index) {
|
||||
inventory.setItem(index, null);
|
||||
Button button = getButton(index);
|
||||
if (button == null) {
|
||||
return;
|
||||
}
|
||||
if (button.isAsynchronous()) {
|
||||
AuLib.inst().getServer().getScheduler().runTaskAsynchronously(AuLib.inst(), ()->{
|
||||
if (button instanceof ItemButton itemButton) {
|
||||
if (itemButton.getItem() != null) {
|
||||
inventory.setItem(index, itemButton.getItem());
|
||||
return;
|
||||
}
|
||||
}
|
||||
inventory.setItem(index, button.getItemStack());
|
||||
});
|
||||
} else {
|
||||
if (button instanceof ItemButton itemButton) {
|
||||
if (itemButton.getItem() != null) {
|
||||
inventory.setItem(index, itemButton.getItem());
|
||||
return;
|
||||
}
|
||||
}
|
||||
inventory.setItem(index, button.getItemStack());
|
||||
}
|
||||
}
|
||||
|
||||
public final void initButton() {
|
||||
for (int i = 0; i < inventory.getSize(); i++) {
|
||||
inventory.setItem(i, null);
|
||||
}
|
||||
for (Map.Entry<Integer, Button> entry : buttons.entrySet()) {
|
||||
Button button = entry.getValue();
|
||||
if (button.isAsynchronous()) {
|
||||
AuLib.inst().getServer().getScheduler().runTaskAsynchronously(AuLib.inst(), ()->{
|
||||
if (button instanceof ItemButton itemButton) {
|
||||
if (itemButton.getItem() != null) {
|
||||
inventory.setItem(entry.getKey(), itemButton.getItem());
|
||||
return;
|
||||
}
|
||||
}
|
||||
inventory.setItem(entry.getKey(), button.getItemStack());
|
||||
});
|
||||
} else {
|
||||
if (button instanceof ItemButton itemButton) {
|
||||
if (itemButton.getItem() != null) {
|
||||
inventory.setItem(entry.getKey(), itemButton.getItem());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
inventory.setItem(entry.getKey(), button.getItemStack());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Map<Integer, Button> getButtons() {
|
||||
return buttons;
|
||||
}
|
||||
|
||||
}
|
68
src/main/java/com/io/yutian/aulib/gui/GuiHandler.java
Normal file
68
src/main/java/com/io/yutian/aulib/gui/GuiHandler.java
Normal file
|
@ -0,0 +1,68 @@
|
|||
package com.io.yutian.aulib.gui;
|
||||
|
||||
import com.io.yutian.aulib.listener.IListener;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.inventory.InventoryAction;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.event.inventory.InventoryCloseEvent;
|
||||
import org.bukkit.event.inventory.InventoryDragEvent;
|
||||
import org.bukkit.inventory.InventoryHolder;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
public class GuiHandler extends IListener {
|
||||
|
||||
public GuiHandler(Plugin plugin) {
|
||||
super(plugin);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void onInventoryClick(InventoryClickEvent event) {
|
||||
if (event.getInventory().getHolder() == null) {
|
||||
return;
|
||||
}
|
||||
Player player = (Player) event.getWhoClicked();
|
||||
InventoryHolder holder = event.getInventory().getHolder();
|
||||
if (holder instanceof IGui iGui) {
|
||||
if (event.getClickedInventory() != event.getInventory()) {
|
||||
if (event.getAction().equals(InventoryAction.MOVE_TO_OTHER_INVENTORY) || event.getAction().equals(InventoryAction.COLLECT_TO_CURSOR)) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (event.getAction().equals(InventoryAction.HOTBAR_SWAP) || event.getAction().equals(InventoryAction.HOTBAR_MOVE_AND_READD)) {
|
||||
event.setCancelled(true);
|
||||
player.getInventory().setItemInOffHand(player.getInventory().getItemInOffHand());
|
||||
return;
|
||||
}
|
||||
int slot = event.getRawSlot();
|
||||
iGui.handler(player, slot, event);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onInventoryDrag(InventoryDragEvent event) {
|
||||
if (event.getInventory().getHolder() != null) {
|
||||
InventoryHolder inventoryHolder = event.getInventory().getHolder();
|
||||
if (inventoryHolder instanceof IGui) {
|
||||
if (inventoryHolder instanceof IGuiDrag iGuiDrag) {
|
||||
iGuiDrag.onInventoryDrag(event);
|
||||
} else {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onInventoryClose(InventoryCloseEvent event) {
|
||||
if (event.getInventory().getHolder() != null) {
|
||||
InventoryHolder inventoryHolder = event.getInventory().getHolder();
|
||||
if (inventoryHolder instanceof IGui iGui) {
|
||||
iGui.close(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
142
src/main/java/com/io/yutian/aulib/gui/IGui.java
Normal file
142
src/main/java/com/io/yutian/aulib/gui/IGui.java
Normal file
|
@ -0,0 +1,142 @@
|
|||
package com.io.yutian.aulib.gui;
|
||||
|
||||
import com.io.yutian.aulib.gui.button.Button;
|
||||
import com.io.yutian.aulib.gui.button.ButtonHandler;
|
||||
import com.io.yutian.aulib.gui.button.ItemButton;
|
||||
import com.io.yutian.aulib.gui.button.ItemSlotButton;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.event.inventory.InventoryCloseEvent;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.InventoryHolder;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public abstract class IGui implements InventoryHolder {
|
||||
|
||||
public Inventory inventory;
|
||||
public Player player;
|
||||
|
||||
private String title;
|
||||
private int size;
|
||||
|
||||
public IGui(Player player, String title, int size) {
|
||||
this.inventory = Bukkit.createInventory(this, size, Component.text(title));
|
||||
this.title = title;
|
||||
this.size = size;
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
public abstract void init();
|
||||
|
||||
public abstract void handler(Player player, int slot, InventoryClickEvent event);
|
||||
|
||||
public void close(InventoryCloseEvent event) {
|
||||
}
|
||||
|
||||
public void open() {
|
||||
player.openInventory(inventory);
|
||||
}
|
||||
|
||||
public void clickButton(InventoryClickEvent event, int slot, Button button) {
|
||||
if (button instanceof ItemButton itemButton) {
|
||||
ItemStack itemStack = event.getCurrentItem();
|
||||
ItemStack item = event.getCursor();
|
||||
if (itemButton.isItem(itemStack)) {
|
||||
if (item != null & !item.getType().equals(Material.AIR)) {
|
||||
if (itemButton.getPutPredicate() != null && !itemButton.getPutPredicate().test(player, item)) {
|
||||
return;
|
||||
}
|
||||
if (itemButton.getClickItemConsumer() != null) {
|
||||
itemButton.getClickItemConsumer().accept(player, item);
|
||||
}
|
||||
player.setItemOnCursor(null);
|
||||
if (itemButton.getPutItemFunction() != null) {
|
||||
ItemStack itemStack1 = itemButton.getPutItemFunction().apply(item);
|
||||
itemButton.setItem(itemStack1);
|
||||
inventory.setItem(slot, itemStack1);
|
||||
} else {
|
||||
itemButton.setItem(item);
|
||||
inventory.setItem(slot, item);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (item == null || item.getType().equals(Material.AIR)) {
|
||||
if (itemButton.getClickItemConsumer() != null) {
|
||||
itemButton.getClickItemConsumer().accept(player, item);
|
||||
}
|
||||
player.setItemOnCursor(itemStack);
|
||||
itemButton.setItem(null);
|
||||
inventory.setItem(slot, button.getItemStack());
|
||||
} else {
|
||||
if (itemButton.getPutPredicate() != null && !itemButton.getPutPredicate().test(player, item)) {
|
||||
return;
|
||||
}
|
||||
player.setItemOnCursor(itemStack);
|
||||
if (itemButton.getPutItemFunction() != null) {
|
||||
ItemStack itemStack1 = itemButton.getPutItemFunction().apply(item);
|
||||
if (itemButton.getClickItemConsumer() != null) {
|
||||
itemButton.getClickItemConsumer().accept(player, itemStack1);
|
||||
}
|
||||
itemButton.setItem(itemStack1);
|
||||
inventory.setItem(slot, itemStack1);
|
||||
} else {
|
||||
if (itemButton.getClickItemConsumer() != null) {
|
||||
itemButton.getClickItemConsumer().accept(player, item);
|
||||
}
|
||||
itemButton.setItem(item);
|
||||
inventory.setItem(slot, item);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (button instanceof ItemSlotButton itemSlotButton) {
|
||||
ItemStack itemStack = event.getCurrentItem();
|
||||
ItemStack item = event.getCursor();
|
||||
if (item == null || item.getType().equals(Material.AIR)) {
|
||||
if (itemStack == null || itemStack.getType().equals(Material.AIR)) {
|
||||
return;
|
||||
}
|
||||
inventory.setItem(slot, null);
|
||||
itemSlotButton.setItemStack(null);
|
||||
player.setItemOnCursor(itemStack);
|
||||
if (itemSlotButton.getPickItemFunction() != null) {
|
||||
itemSlotButton.getPickItemFunction().accept(itemStack);
|
||||
}
|
||||
} else {
|
||||
if (itemStack == null || itemStack.getType().equals(Material.AIR)) {
|
||||
if (!itemSlotButton.isCanPut()) {
|
||||
return;
|
||||
}
|
||||
player.setItemOnCursor(null);
|
||||
itemSlotButton.setItemStack(item);
|
||||
inventory.setItem(slot, item);
|
||||
if (itemSlotButton.getPutItemFunction() != null) {
|
||||
itemSlotButton.getPutItemFunction().accept(item);
|
||||
}
|
||||
} else {
|
||||
if (!itemSlotButton.isCanPut()) {
|
||||
return;
|
||||
}
|
||||
player.setItemOnCursor(itemStack);
|
||||
itemSlotButton.setItemStack(item);
|
||||
inventory.setItem(slot, item);
|
||||
if (itemSlotButton.getPutItemFunction() != null) {
|
||||
itemSlotButton.getPutItemFunction().accept(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (button instanceof ButtonHandler buttonHandler) {
|
||||
buttonHandler.handler(event, slot, button);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Inventory getInventory() {
|
||||
return inventory;
|
||||
}
|
||||
|
||||
}
|
9
src/main/java/com/io/yutian/aulib/gui/IGuiDrag.java
Normal file
9
src/main/java/com/io/yutian/aulib/gui/IGuiDrag.java
Normal file
|
@ -0,0 +1,9 @@
|
|||
package com.io.yutian.aulib.gui;
|
||||
|
||||
import org.bukkit.event.inventory.InventoryDragEvent;
|
||||
|
||||
public interface IGuiDrag {
|
||||
|
||||
void onInventoryDrag(InventoryDragEvent event);
|
||||
|
||||
}
|
175
src/main/java/com/io/yutian/aulib/gui/PageGui.java
Normal file
175
src/main/java/com/io/yutian/aulib/gui/PageGui.java
Normal file
|
@ -0,0 +1,175 @@
|
|||
package com.io.yutian.aulib.gui;
|
||||
|
||||
import com.io.yutian.aulib.AuLib;
|
||||
import com.io.yutian.aulib.gui.button.Button;
|
||||
import com.io.yutian.aulib.gui.button.ClickType;
|
||||
import com.io.yutian.aulib.gui.button.ItemButton;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.InventoryAction;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class PageGui extends IGui {
|
||||
|
||||
private int page = 1;
|
||||
private int maxPage = 1;
|
||||
|
||||
private Map<Integer, Page> pages = new HashMap<>();
|
||||
|
||||
public PageGui(Player player, String title, int size, int maxPage) {
|
||||
super(player, title, size);
|
||||
this.maxPage = maxPage;
|
||||
}
|
||||
|
||||
public void initButton() {
|
||||
initButton(this.page);
|
||||
}
|
||||
|
||||
public void initButton(int page) {
|
||||
if (page > pages.size()) {
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < inventory.getSize(); i++) {
|
||||
inventory.setItem(i, null);
|
||||
}
|
||||
if (pages.containsKey(page)) {
|
||||
Page page1 = pages.get(page);
|
||||
for (Map.Entry<Integer, Button> entry : page1.buttons.entrySet()) {
|
||||
Button button = entry.getValue();
|
||||
if (button.isAsynchronous()) {
|
||||
AuLib.inst().getServer().getScheduler().runTaskAsynchronously(AuLib.inst(), ()->{
|
||||
if (button instanceof ItemButton) {
|
||||
ItemButton itemButton = (ItemButton) button;
|
||||
if (itemButton.getItem() != null) {
|
||||
inventory.setItem(entry.getKey(), itemButton.getItem());
|
||||
return;
|
||||
}
|
||||
}
|
||||
inventory.setItem(entry.getKey(), button.getItemStack());
|
||||
});
|
||||
} else {
|
||||
if (button instanceof ItemButton) {
|
||||
ItemButton itemButton = (ItemButton) button;
|
||||
if (itemButton.getItem() != null) {
|
||||
inventory.setItem(entry.getKey(), itemButton.getItem());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
inventory.setItem(entry.getKey(), button.getItemStack());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handler(Player player, int slot, InventoryClickEvent event) {
|
||||
if (pages.containsKey(page)) {
|
||||
Page page1 = getPage(page);
|
||||
Button button = page1.getButton(slot);
|
||||
if (button == null) {
|
||||
if (slot < inventory.getSize()) {
|
||||
event.setCancelled(true);
|
||||
} else {
|
||||
if (event.getAction().equals(InventoryAction.MOVE_TO_OTHER_INVENTORY)) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
event.setCancelled(true);
|
||||
clickButton(event, slot, button);
|
||||
if (button.isPlaySound()) {
|
||||
player.playSound(player.getLocation(), Sound.UI_BUTTON_CLICK, 1.0f, 1.0f);
|
||||
}
|
||||
InventoryAction action = event.getAction();
|
||||
ClickType clickType = ClickType.LEFT_CLICK;
|
||||
if (action.equals(InventoryAction.PICKUP_ALL)) {
|
||||
clickType = ClickType.LEFT_CLICK;
|
||||
} else if (action.equals(InventoryAction.PICKUP_HALF)) {
|
||||
clickType = ClickType.RIGHT_CLICK;
|
||||
} else if (action.equals(InventoryAction.MOVE_TO_OTHER_INVENTORY)) {
|
||||
clickType = ClickType.SHIFT_CLICK;
|
||||
}
|
||||
if (button.getClickConsumer() != null) {
|
||||
button.getClickConsumer().accept(player, clickType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Page getPage(int page) {
|
||||
if (page <= 0 || page > maxPage) {
|
||||
return null;
|
||||
}
|
||||
if (!pages.containsKey(page)) {
|
||||
pages.put(page, new Page());
|
||||
}
|
||||
return pages.get(page);
|
||||
}
|
||||
|
||||
public void setPage(int page) {
|
||||
this.page = page;
|
||||
}
|
||||
|
||||
public void next() {
|
||||
if (page >= maxPage) {
|
||||
return;
|
||||
}
|
||||
this.page ++;
|
||||
initButton();
|
||||
}
|
||||
|
||||
public void up() {
|
||||
if (page <= 1) {
|
||||
return;
|
||||
}
|
||||
this.page --;
|
||||
initButton();
|
||||
}
|
||||
|
||||
public int getPage() {
|
||||
return page;
|
||||
}
|
||||
|
||||
public int getMaxPage() {
|
||||
return maxPage;
|
||||
}
|
||||
|
||||
public void setMaxPage(int maxPage) {
|
||||
this.maxPage = maxPage;
|
||||
}
|
||||
|
||||
public void addButton(int page, int index, Button button) {
|
||||
Page page1 = pages.getOrDefault(page, new Page());
|
||||
page1.buttons.put(index, button);
|
||||
pages.put(page, page1);
|
||||
}
|
||||
|
||||
public static class Page {
|
||||
|
||||
private Map<Integer, Button> buttons = new HashMap<>();
|
||||
|
||||
public Page() {
|
||||
}
|
||||
|
||||
public void addButton(int index, Button button) {
|
||||
buttons.put(index, button);
|
||||
}
|
||||
|
||||
public Button getButton(int index) {
|
||||
return buttons.getOrDefault(index, null);
|
||||
}
|
||||
|
||||
public Map<Integer, Button> getButtons() {
|
||||
return buttons;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
56
src/main/java/com/io/yutian/aulib/gui/button/Button.java
Normal file
56
src/main/java/com/io/yutian/aulib/gui/button/Button.java
Normal file
|
@ -0,0 +1,56 @@
|
|||
package com.io.yutian.aulib.gui.button;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
public class Button {
|
||||
|
||||
private ItemStack itemStack;
|
||||
|
||||
private BiConsumer<Player, ClickType> clickConsumer;
|
||||
|
||||
private boolean asynchronous = false;
|
||||
private boolean playSound = true;
|
||||
|
||||
public Button(ItemStack itemStack) {
|
||||
this.itemStack = itemStack;
|
||||
}
|
||||
|
||||
public void setItemStack(ItemStack itemStack) {
|
||||
this.itemStack = itemStack;
|
||||
}
|
||||
|
||||
public Button click(BiConsumer<Player, ClickType> consumer) {
|
||||
this.clickConsumer = consumer;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Button asyn() {
|
||||
this.asynchronous = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Button noSound() {
|
||||
this.playSound = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStack getItemStack() {
|
||||
return itemStack;
|
||||
}
|
||||
|
||||
public BiConsumer<Player, ClickType> getClickConsumer() {
|
||||
return clickConsumer;
|
||||
}
|
||||
|
||||
public boolean isAsynchronous() {
|
||||
return asynchronous;
|
||||
}
|
||||
|
||||
public boolean isPlaySound() {
|
||||
return playSound;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package com.io.yutian.aulib.gui.button;
|
||||
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
|
||||
public interface ButtonHandler {
|
||||
|
||||
void handler(InventoryClickEvent event, int slot, Button button);
|
||||
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package com.io.yutian.aulib.gui.button;
|
||||
|
||||
public enum ClickType {
|
||||
|
||||
LEFT_CLICK,
|
||||
RIGHT_CLICK,
|
||||
SHIFT_CLICK
|
||||
|
||||
}
|
72
src/main/java/com/io/yutian/aulib/gui/button/ItemButton.java
Normal file
72
src/main/java/com/io/yutian/aulib/gui/button/ItemButton.java
Normal file
|
@ -0,0 +1,72 @@
|
|||
package com.io.yutian.aulib.gui.button;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.BiPredicate;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class ItemButton extends Button {
|
||||
|
||||
private BiConsumer<Player, ItemStack> clickItemConsumer;
|
||||
|
||||
private Function<ItemStack, ItemStack> putItemFunction;
|
||||
private BiPredicate<Player, ItemStack> putPredicate;
|
||||
|
||||
private ItemStack item;
|
||||
|
||||
public ItemButton(ItemStack itemStack) {
|
||||
super(itemStack);
|
||||
|
||||
NBTItem nbtItem = new NBTItem(item);
|
||||
nbtItem.setString("gui_meta", "item_button");
|
||||
setItemStack(nbtItem.getItem());
|
||||
}
|
||||
|
||||
public ItemButton setItem(ItemStack item) {
|
||||
this.item = item;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStack getItem() {
|
||||
return item;
|
||||
}
|
||||
|
||||
public ItemButton itemPredicate(BiPredicate<Player, ItemStack> predicate) {
|
||||
this.putPredicate = predicate;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemButton putItem(Function<ItemStack, ItemStack> putItemFunction) {
|
||||
this.putItemFunction = putItemFunction;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isItem() {
|
||||
return isItem(item);
|
||||
}
|
||||
|
||||
public boolean isItem(ItemStack item) {
|
||||
NBTItem nbtItem = new NBTItem(item);
|
||||
return nbtItem.hasTag("gui_meta", NBTType.NBTTagString) && nbtItem.getString("gui_meta").equalsIgnoreCase("item_button");
|
||||
}
|
||||
|
||||
public ItemButton clickItem(BiConsumer<Player, ItemStack> consumer) {
|
||||
this.clickItemConsumer = consumer;
|
||||
return this;
|
||||
}
|
||||
|
||||
public BiConsumer<Player, ItemStack> getClickItemConsumer() {
|
||||
return clickItemConsumer;
|
||||
}
|
||||
|
||||
public Function<ItemStack, ItemStack> getPutItemFunction() {
|
||||
return putItemFunction;
|
||||
}
|
||||
|
||||
public BiPredicate<Player, ItemStack> getPutPredicate() {
|
||||
return putPredicate;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
package com.io.yutian.aulib.gui.button;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class ItemSlotButton extends Button {
|
||||
|
||||
private Consumer<ItemStack> putItemFunction;
|
||||
private Consumer<ItemStack> pickItemFunction;
|
||||
|
||||
private boolean canPut = true;
|
||||
|
||||
public ItemSlotButton() {
|
||||
super(new ItemStack(Material.AIR));
|
||||
}
|
||||
|
||||
public ItemSlotButton putItem(Consumer<ItemStack> putItemConsumer) {
|
||||
this.putItemFunction = putItemConsumer;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemSlotButton pickItem(Consumer<ItemStack> pickItemConsumer) {
|
||||
this.pickItemFunction = pickItemConsumer;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemSlotButton canPut(boolean can) {
|
||||
this.canPut = can;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isCanPut() {
|
||||
return canPut;
|
||||
}
|
||||
|
||||
public Consumer<ItemStack> getPickItemFunction() {
|
||||
return pickItemFunction;
|
||||
}
|
||||
|
||||
public Consumer<ItemStack> getPutItemFunction() {
|
||||
return putItemFunction;
|
||||
}
|
||||
|
||||
}
|
81
src/main/java/com/io/yutian/aulib/lang/Lang.java
Normal file
81
src/main/java/com/io/yutian/aulib/lang/Lang.java
Normal file
|
@ -0,0 +1,81 @@
|
|||
package com.io.yutian.aulib.lang;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class Lang {
|
||||
|
||||
private static Map<Plugin, List<File>> langFileMap = new HashMap<>();
|
||||
|
||||
private static Map<String, String> langMap = new HashMap<>();
|
||||
|
||||
public static String get(String key) {
|
||||
return langMap.getOrDefault(key, "§o"+key);
|
||||
}
|
||||
|
||||
public static String get(String key, Object... args) {
|
||||
String s = langMap.getOrDefault(key, "§o"+key);
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
s = s.replace("$"+i, String.valueOf(args[i]));
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
public static void reload(Plugin plugin) {
|
||||
if (!langFileMap.containsKey(plugin)) {
|
||||
return;
|
||||
}
|
||||
List<File> list = langFileMap.get(plugin);
|
||||
list.forEach(Lang::loadFile);
|
||||
}
|
||||
|
||||
public static void reload() {
|
||||
langMap.clear();
|
||||
for (List<File> files : langFileMap.values()) {
|
||||
files.forEach(Lang::loadFile);
|
||||
}
|
||||
}
|
||||
|
||||
private static void loadFile(File file) {
|
||||
FileConfiguration fileConfiguration = YamlConfiguration.loadConfiguration(file);
|
||||
for (String key : fileConfiguration.getKeys(true)) {
|
||||
if (!fileConfiguration.isString(key)) {
|
||||
continue;
|
||||
}
|
||||
String string = fileConfiguration.getString(key);
|
||||
string = ChatColor.translateAlternateColorCodes('&', string);
|
||||
langMap.put(key, string);
|
||||
}
|
||||
}
|
||||
|
||||
public static void registerLangFile(Plugin plugin) {
|
||||
registerLangFile(plugin, getFile(plugin));
|
||||
}
|
||||
|
||||
public static void registerLangFile(Plugin plugin, File file) {
|
||||
if (!file.exists()) {
|
||||
return;
|
||||
}
|
||||
List<File> files = langFileMap.getOrDefault(plugin, new ArrayList<>());
|
||||
files.add(file);
|
||||
langFileMap.put(plugin, files);
|
||||
loadFile(file);
|
||||
}
|
||||
|
||||
public static File getFile(Plugin plugin) {
|
||||
File file = new File(plugin.getDataFolder()+File.separator+ "lang.yml");
|
||||
if (!file.exists()) {
|
||||
plugin.saveResource("lang.yml", false);
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
}
|
53
src/main/java/com/io/yutian/aulib/list/PageList.java
Normal file
53
src/main/java/com/io/yutian/aulib/list/PageList.java
Normal file
|
@ -0,0 +1,53 @@
|
|||
package com.io.yutian.aulib.list;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class PageList<T> {
|
||||
|
||||
private List<T> list;
|
||||
private Map<Integer, List<T>> map = new HashMap<>();
|
||||
private int amount;
|
||||
|
||||
public PageList(List<T> list, int amount) {
|
||||
this.list = list;
|
||||
this.amount = amount;
|
||||
if (list == null) {
|
||||
return;
|
||||
}
|
||||
if (list.size() <= amount) {
|
||||
List<T> newList = new ArrayList<T>();
|
||||
list.forEach(o-> newList.add(o));
|
||||
map.put(1, newList);
|
||||
} else {
|
||||
int x = 0;
|
||||
int c = list.size() / amount;
|
||||
for (int j = 0; j <= c;j++) {
|
||||
int min = j * amount;
|
||||
int max = (j+1) * amount;
|
||||
List<T> newList = new ArrayList<T>();
|
||||
for (int k = min; k < max; k++) {
|
||||
if (k >= list.size()) {
|
||||
break;
|
||||
}
|
||||
newList.add(list.get(k));
|
||||
}
|
||||
map.put(j+1, newList);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return map.size();
|
||||
}
|
||||
|
||||
public List<T> getList(int page) {
|
||||
if (page <= 0) {
|
||||
page = 1;
|
||||
}
|
||||
return map.get(page);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
package com.io.yutian.aulib.listener;
|
||||
|
||||
import com.io.yutian.aulib.gui.IGui;
|
||||
import com.io.yutian.aulib.gui.IGuiDrag;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.inventory.*;
|
||||
import org.bukkit.inventory.InventoryHolder;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
public final class GuiHandlerListener extends IListener {
|
||||
|
||||
public GuiHandlerListener(Plugin plugin) {
|
||||
super(plugin);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void onInventoryClick(InventoryClickEvent event) {
|
||||
if (event.getInventory().getHolder() == null) {
|
||||
return;
|
||||
}
|
||||
Player player = (Player) event.getWhoClicked();
|
||||
InventoryHolder holder = event.getInventory().getHolder();
|
||||
if (holder instanceof IGui iGui) {
|
||||
if (event.getClickedInventory() != event.getInventory()) {
|
||||
if (event.getAction().equals(InventoryAction.MOVE_TO_OTHER_INVENTORY) || event.getAction().equals(InventoryAction.COLLECT_TO_CURSOR)) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (event.getAction().equals(InventoryAction.HOTBAR_SWAP) || event.getAction().equals(InventoryAction.HOTBAR_MOVE_AND_READD)) {
|
||||
event.setCancelled(true);
|
||||
player.getInventory().setItemInOffHand(player.getInventory().getItemInOffHand());
|
||||
return;
|
||||
}
|
||||
int slot = event.getRawSlot();
|
||||
iGui.handler(player, slot, event);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onInventoryDrag(InventoryDragEvent event) {
|
||||
if (event.getInventory().getHolder() != null) {
|
||||
InventoryHolder inventoryHolder = event.getInventory().getHolder();
|
||||
if (inventoryHolder instanceof IGui) {
|
||||
if (inventoryHolder instanceof IGuiDrag iGuiDrag) {
|
||||
iGuiDrag.onInventoryDrag(event);
|
||||
} else {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onInventoryClose(InventoryCloseEvent event) {
|
||||
if (event.getInventory().getHolder() != null) {
|
||||
InventoryHolder inventoryHolder = event.getInventory().getHolder();
|
||||
if (inventoryHolder instanceof IGui iGui) {
|
||||
iGui.close(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
12
src/main/java/com/io/yutian/aulib/listener/IListener.java
Normal file
12
src/main/java/com/io/yutian/aulib/listener/IListener.java
Normal file
|
@ -0,0 +1,12 @@
|
|||
package com.io.yutian.aulib.listener;
|
||||
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
public class IListener implements Listener {
|
||||
|
||||
public IListener(Plugin plugin) {
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
}
|
||||
|
||||
}
|
180
src/main/java/com/io/yutian/aulib/nbt/INBT.java
Normal file
180
src/main/java/com/io/yutian/aulib/nbt/INBT.java
Normal file
|
@ -0,0 +1,180 @@
|
|||
package com.io.yutian.aulib.nbt;
|
||||
|
||||
import net.minecraft.nbt.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public interface INBT {
|
||||
|
||||
Object getValue();
|
||||
|
||||
byte getTypeId();
|
||||
|
||||
private static String getNBTTag(byte typeByte) {
|
||||
return switch (typeByte) {
|
||||
case 1 -> "NBTTagByte";
|
||||
case 2 -> "NBTTagShort";
|
||||
case 3 -> "NBTTagInt";
|
||||
case 4 -> "NBTTagLong";
|
||||
case 5 -> "NBTTagFloat";
|
||||
case 6 -> "NBTTagDouble";
|
||||
case 7 -> "NBTTagByteArray";
|
||||
case 8 -> "NBTTagString";
|
||||
case 9 -> "NBTTagList";
|
||||
case 10 -> "NBTTagCompound";
|
||||
case 11 -> "NBTTagIntArray";
|
||||
case 12 -> "NBTTagLongArray";
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
|
||||
static INBT asObject(Object object) {
|
||||
if (object instanceof Byte b) {
|
||||
return new NBTByte(b);
|
||||
} else if (object instanceof Short value) {
|
||||
return new NBTShort(value);
|
||||
} else if (object instanceof Integer value) {
|
||||
return new NBTInt(value);
|
||||
} else if (object instanceof Long value) {
|
||||
return new NBTLong(value);
|
||||
} else if (object instanceof Float value) {
|
||||
return new NBTFloat(value);
|
||||
} else if (object instanceof Double value) {
|
||||
return new NBTDouble(value);
|
||||
} else if (object instanceof byte[] value) {
|
||||
return new NBTByteArray(value);
|
||||
} else if (object instanceof String value) {
|
||||
return new NBTString(value);
|
||||
} else if (object instanceof int[] value) {
|
||||
return new NBTIntArray(value);
|
||||
} else if (object instanceof long[] value) {
|
||||
return new NBTLongArray(value);
|
||||
} else if (object instanceof Boolean b) {
|
||||
return new NBTByte((byte) (b ? 1 : 0));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static net.minecraft.nbt.NBTBase asNMS(INBT nbt) {
|
||||
byte type = nbt.getTypeId();
|
||||
switch (type) {
|
||||
case 1 -> {
|
||||
NBTByte nbtByte = (NBTByte) nbt;
|
||||
return NBTTagByte.a(nbtByte.getByte());
|
||||
}
|
||||
case 2 -> {
|
||||
NBTShort nbtShort = (NBTShort) nbt;
|
||||
return NBTTagShort.a(nbtShort.getShort());
|
||||
}
|
||||
case 3 -> {
|
||||
NBTInt nbtInt = (NBTInt) nbt;
|
||||
return NBTTagInt.a(nbtInt.getInt());
|
||||
}
|
||||
case 4 -> {
|
||||
NBTLong nbtLong = (NBTLong) nbt;
|
||||
return NBTTagLong.a(nbtLong.getLong());
|
||||
}
|
||||
case 5 -> {
|
||||
NBTFloat nbtfloat = (NBTFloat) nbt;
|
||||
return NBTTagFloat.a(nbtfloat.getFloat());
|
||||
}
|
||||
case 6 -> {
|
||||
NBTDouble nbtDouble = (NBTDouble) nbt;
|
||||
return NBTTagDouble.a(nbtDouble.getDouble());
|
||||
}
|
||||
case 7 -> {
|
||||
NBTByteArray nbtByteArray = (NBTByteArray) nbt;
|
||||
return new NBTTagByteArray(nbtByteArray.getByteArray());
|
||||
}
|
||||
case 8 -> {
|
||||
NBTString nbtString = (NBTString) nbt;
|
||||
return NBTTagString.a(nbtString.getString());
|
||||
}
|
||||
case 9 -> {
|
||||
NBTList nbtTagList = (NBTList) nbt;
|
||||
List<net.minecraft.nbt.NBTBase> list = new ArrayList<>();
|
||||
for (Object base : nbtTagList.getList()) {
|
||||
list.add(asNMS((INBT) base));
|
||||
}
|
||||
NBTTagList nbtTagList1 = new NBTTagList();
|
||||
for (net.minecraft.nbt.NBTBase nbt1 : list) {
|
||||
nbtTagList1.add(nbt1);
|
||||
}
|
||||
return nbtTagList1;
|
||||
}
|
||||
case 10 -> {
|
||||
NBTCompound nbtCompound = (NBTCompound) nbt;
|
||||
NBTTagCompound nbtTagCompound = new NBTTagCompound();
|
||||
for (String key : nbtCompound.keySet()) {
|
||||
INBT nbt1 = nbtCompound.get(key);
|
||||
nbtTagCompound.a(key, asNMS(nbt1));
|
||||
}
|
||||
return nbtTagCompound;
|
||||
}
|
||||
case 11 -> {
|
||||
NBTIntArray nbtIntArray = (NBTIntArray) nbt;
|
||||
return new NBTTagIntArray(nbtIntArray.getIntArray());
|
||||
}
|
||||
case 12 -> {
|
||||
NBTLongArray nbtLongArray = (NBTLongArray) nbt;
|
||||
return new NBTTagLongArray(nbtLongArray.getLongArray());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static INBT as(net.minecraft.nbt.NBTBase nbtBase) {
|
||||
byte type = nbtBase.a();
|
||||
switch (type) {
|
||||
case 1:
|
||||
NBTTagByte nbtTagByte = (NBTTagByte) nbtBase;
|
||||
return new NBTByte(nbtTagByte.h());
|
||||
case 2:
|
||||
NBTTagShort nbtTagShort = (NBTTagShort) nbtBase;
|
||||
return new NBTShort(nbtTagShort.g());
|
||||
case 3:
|
||||
NBTTagInt nbtTagInt = (NBTTagInt) nbtBase;
|
||||
return new NBTInt(nbtTagInt.f());
|
||||
case 4:
|
||||
NBTTagLong nbtTagLong = (NBTTagLong) nbtBase;
|
||||
return new NBTLong(nbtTagLong.e());
|
||||
case 5:
|
||||
NBTTagFloat nbtTagFloat = (NBTTagFloat) nbtBase;
|
||||
return new NBTFloat(nbtTagFloat.j());
|
||||
case 6:
|
||||
NBTTagDouble nbtTagDouble = (NBTTagDouble) nbtBase;
|
||||
return new NBTDouble(nbtTagDouble.i());
|
||||
case 7:
|
||||
NBTTagByteArray tagByteArray = (NBTTagByteArray) nbtBase;
|
||||
return new NBTByteArray(tagByteArray.d());
|
||||
case 8:
|
||||
NBTTagString nbtTagString = (NBTTagString) nbtBase;
|
||||
return new NBTString(nbtTagString.e_());
|
||||
case 9:
|
||||
NBTTagList nbtTagList = (NBTTagList) nbtBase;
|
||||
List<INBT> list = new ArrayList<>();
|
||||
for (net.minecraft.nbt.NBTBase base : nbtTagList) {
|
||||
list.add(as(base));
|
||||
}
|
||||
return new NBTList(list);
|
||||
case 10:
|
||||
NBTTagCompound nbtTagCompound = (NBTTagCompound) nbtBase;
|
||||
Map<String, INBT> map = new HashMap<>();
|
||||
for (String key : nbtTagCompound.d()) {
|
||||
map.put(key, as(nbtTagCompound.c(key)));
|
||||
}
|
||||
return new NBTCompound(map);
|
||||
case 11:
|
||||
NBTTagIntArray nbtTagIntArray = (NBTTagIntArray) nbtBase;
|
||||
return new NBTIntArray(nbtTagIntArray.f());
|
||||
case 12:
|
||||
NBTTagLongArray nbtTagLongArray = (NBTTagLongArray) nbtBase;
|
||||
return new NBTLongArray(nbtTagLongArray.f());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
67
src/main/java/com/io/yutian/aulib/nbt/NBTByte.java
Normal file
67
src/main/java/com/io/yutian/aulib/nbt/NBTByte.java
Normal file
|
@ -0,0 +1,67 @@
|
|||
package com.io.yutian.aulib.nbt;
|
||||
|
||||
public class NBTByte extends NBTNumber {
|
||||
|
||||
public static byte TYPE_ID = 1;
|
||||
|
||||
private byte value;
|
||||
|
||||
public NBTByte(byte value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public NBTByte() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte getTypeId() {
|
||||
return TYPE_ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLong() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInt() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getShort() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte getByte() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getDouble() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getFloat() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public static NBTByte a(boolean var0) {
|
||||
return var0 ? new NBTByte((byte) 1) : new NBTByte((byte) 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "NBTByte{" +
|
||||
"value=" + value +
|
||||
'}';
|
||||
}
|
||||
|
||||
}
|
35
src/main/java/com/io/yutian/aulib/nbt/NBTByteArray.java
Normal file
35
src/main/java/com/io/yutian/aulib/nbt/NBTByteArray.java
Normal file
|
@ -0,0 +1,35 @@
|
|||
package com.io.yutian.aulib.nbt;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class NBTByteArray extends INBT {
|
||||
|
||||
public static byte TYPE_ID = 7;
|
||||
|
||||
private byte[] value;
|
||||
|
||||
public NBTByteArray(byte[] value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public byte[] getByteArray() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte getTypeId() {
|
||||
return TYPE_ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "NBTByteArray{" +
|
||||
"value=" + Arrays.toString(value) +
|
||||
'}';
|
||||
}
|
||||
}
|
232
src/main/java/com/io/yutian/aulib/nbt/NBTCompound.java
Normal file
232
src/main/java/com/io/yutian/aulib/nbt/NBTCompound.java
Normal file
|
@ -0,0 +1,232 @@
|
|||
package com.io.yutian.aulib.nbt;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
public class NBTCompound implements INBT {
|
||||
|
||||
public static byte TYPE_ID = 10;
|
||||
|
||||
private Map<String, INBT> nbtMap = new HashMap<>();
|
||||
|
||||
public NBTCompound() {
|
||||
}
|
||||
|
||||
public NBTCompound(Map<String, INBT> nbtMap) {
|
||||
this.nbtMap = nbtMap;
|
||||
}
|
||||
|
||||
public Set<String> keySet() {
|
||||
return nbtMap.keySet();
|
||||
}
|
||||
|
||||
public Map<String, INBT> getMap() {
|
||||
return nbtMap;
|
||||
}
|
||||
|
||||
public void remove(String key) {
|
||||
nbtMap.remove(key);
|
||||
}
|
||||
|
||||
public boolean hasKey(String key) {
|
||||
return this.nbtMap.containsKey(key);
|
||||
}
|
||||
|
||||
public boolean hasKey(String key, byte id) {
|
||||
return this.nbtMap.containsKey(key) && this.nbtMap.get(key).getTypeId() == id;
|
||||
}
|
||||
|
||||
public boolean hasKey(String key, int id) {
|
||||
return this.nbtMap.containsKey(key) && this.nbtMap.get(key).getTypeId() == id;
|
||||
}
|
||||
|
||||
public NBTList getList(String key) {
|
||||
INBT list = this.nbtMap.get(key);
|
||||
if (list == null || list.getTypeId() != 9) {
|
||||
return null;
|
||||
}
|
||||
return (NBTList) list;
|
||||
}
|
||||
|
||||
public NBTCompound getCompound(String key) {
|
||||
INBT comound = this.nbtMap.get(key);
|
||||
if (comound == null || comound.getTypeId() != 10) {
|
||||
return null;
|
||||
}
|
||||
return (NBTCompound) comound;
|
||||
}
|
||||
|
||||
public INBT get(String key) {
|
||||
return this.nbtMap.get(key);
|
||||
}
|
||||
|
||||
public int getInt(String key) {
|
||||
INBT nbt = this.nbtMap.get(key);
|
||||
if (nbt == null || nbt.getTypeId() != 3) {
|
||||
return 0;
|
||||
}
|
||||
return ((NBTInt) nbt).getInt();
|
||||
}
|
||||
|
||||
public String getString(String key) {
|
||||
INBT nbt = this.nbtMap.get(key);
|
||||
if (nbt == null || nbt.getTypeId() != 8) {
|
||||
return null;
|
||||
}
|
||||
return ((NBTString) nbt).getString();
|
||||
}
|
||||
|
||||
public double getDouble(String key) {
|
||||
INBT nbt = this.nbtMap.get(key);
|
||||
if (nbt == null || nbt.getTypeId() != 6) {
|
||||
return 0.0;
|
||||
}
|
||||
return ((NBTDouble) nbt).getDouble();
|
||||
}
|
||||
|
||||
public float getFloat(String key) {
|
||||
INBT nbt = this.nbtMap.get(key);
|
||||
if (nbt == null || nbt.getTypeId() != 5) {
|
||||
return 0.0F;
|
||||
}
|
||||
return ((NBTFloat) nbt).getFloat();
|
||||
}
|
||||
|
||||
public short getShort(String key) {
|
||||
INBT nbt = this.nbtMap.get(key);
|
||||
if (nbt == null || nbt.getTypeId() != 2) {
|
||||
return 0;
|
||||
}
|
||||
return ((NBTShort) nbt).getShort();
|
||||
}
|
||||
|
||||
public long getLong(String key) {
|
||||
INBT nbt = this.nbtMap.get(key);
|
||||
if (nbt == null || nbt.getTypeId() != 4) {
|
||||
return 0;
|
||||
}
|
||||
return ((NBTLong) nbt).getLong();
|
||||
}
|
||||
|
||||
public byte getByte(String key) {
|
||||
INBT nbt = this.nbtMap.get(key);
|
||||
if (nbt == null || nbt.getTypeId() != 1) {
|
||||
return 0;
|
||||
}
|
||||
return ((NBTByte) nbt).getByte();
|
||||
}
|
||||
|
||||
public NBTByteArray getByteArray(String key) {
|
||||
INBT nbt = this.nbtMap.get(key);
|
||||
if (nbt == null || nbt.getTypeId() != 7) {
|
||||
return null;
|
||||
}
|
||||
return (NBTByteArray) nbt;
|
||||
}
|
||||
|
||||
public NBTIntArray getIntArray(String key) {
|
||||
INBT nbt = this.nbtMap.get(key);
|
||||
if (nbt == null || nbt.getTypeId() != 11) {
|
||||
return null;
|
||||
}
|
||||
return (NBTIntArray) nbt;
|
||||
}
|
||||
|
||||
public NBTLongArray getLongArray(String key) {
|
||||
INBT nbt = this.nbtMap.get(key);
|
||||
if (nbt == null || nbt.getTypeId() != 12) {
|
||||
return null;
|
||||
}
|
||||
return (NBTLongArray) nbt;
|
||||
}
|
||||
|
||||
public boolean getBoolean(String key) {
|
||||
INBT nbt = this.nbtMap.get(key);
|
||||
if (nbt == null || nbt.getTypeId() != 1) {
|
||||
return false;
|
||||
}
|
||||
return ((NBTByte) nbt).getByte() != 0;
|
||||
}
|
||||
|
||||
public UUID getUUID(String key) {
|
||||
INBT nbt = this.nbtMap.get(key);
|
||||
if (nbt == null || nbt.getTypeId() != 11) {
|
||||
return null;
|
||||
}
|
||||
return a(((NBTIntArray) nbt).getIntArray());
|
||||
}
|
||||
|
||||
public void put(String key, INBT nbt) {
|
||||
this.nbtMap.put(key, nbt);
|
||||
}
|
||||
|
||||
public void putString(String key, String value) {
|
||||
put(key, new NBTString(value));
|
||||
}
|
||||
|
||||
public void putInt(String key, int value) {
|
||||
put(key, new NBTInt(value));
|
||||
}
|
||||
|
||||
public void putShort(String key, short value) {
|
||||
put(key, new NBTShort(value));
|
||||
}
|
||||
|
||||
public void putDouble(String key, double value) {
|
||||
put(key, new NBTDouble(value));
|
||||
}
|
||||
|
||||
public void putLong(String key, long value) {
|
||||
put(key, new NBTLong(value));
|
||||
}
|
||||
|
||||
public void putFloat(String key, float value) {
|
||||
put(key, new NBTFloat(value));
|
||||
}
|
||||
|
||||
public void putByte(String key, byte value) {
|
||||
put(key, new NBTByte(value));
|
||||
}
|
||||
|
||||
public void putBoolean(String key, boolean value) {
|
||||
put(key, NBTByte.a(value));
|
||||
}
|
||||
|
||||
public void putUUID(String key, UUID uuid) {
|
||||
put(key, new NBTIntArray(a(uuid)));
|
||||
}
|
||||
|
||||
private static UUID a(int[] var0) {
|
||||
return new UUID((long)var0[0] << 32 | (long)var0[1] & 4294967295L, (long)var0[2] << 32 | (long)var0[3] & 4294967295L);
|
||||
}
|
||||
|
||||
private static int[] a(UUID var0) {
|
||||
long var1 = var0.getMostSignificantBits();
|
||||
long var3 = var0.getLeastSignificantBits();
|
||||
return a(var1, var3);
|
||||
}
|
||||
|
||||
private static int[] a(long var0, long var2) {
|
||||
return new int[]{(int)(var0 >> 32), (int)var0, (int)(var2 >> 32), (int)var2};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue() {
|
||||
return nbtMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte getTypeId() {
|
||||
return TYPE_ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "NBTCompound{" +
|
||||
"nbtMap=" + nbtMap +
|
||||
'}';
|
||||
}
|
||||
|
||||
}
|
62
src/main/java/com/io/yutian/aulib/nbt/NBTDouble.java
Normal file
62
src/main/java/com/io/yutian/aulib/nbt/NBTDouble.java
Normal file
|
@ -0,0 +1,62 @@
|
|||
package com.io.yutian.aulib.nbt;
|
||||
|
||||
public class NBTDouble extends NBTNumber {
|
||||
|
||||
public static byte TYPE_ID = 6;
|
||||
|
||||
private double value;
|
||||
|
||||
public NBTDouble(double value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public NBTDouble() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte getTypeId() {
|
||||
return TYPE_ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLong() {
|
||||
return (long) this.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInt() {
|
||||
return floor(this.value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getShort() {
|
||||
return (short)(floor(this.value) & 0xFFFF);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte getByte() {
|
||||
return (byte)(floor(this.value) & 0xFF);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getDouble() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getFloat() {
|
||||
return (float) this.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "NBTDouble{" +
|
||||
"value=" + value +
|
||||
'}';
|
||||
}
|
||||
}
|
59
src/main/java/com/io/yutian/aulib/nbt/NBTFloat.java
Normal file
59
src/main/java/com/io/yutian/aulib/nbt/NBTFloat.java
Normal file
|
@ -0,0 +1,59 @@
|
|||
package com.io.yutian.aulib.nbt;
|
||||
|
||||
public class NBTFloat extends NBTNumber {
|
||||
|
||||
public static byte TYPE_ID = 5;
|
||||
|
||||
private float value;
|
||||
|
||||
public NBTFloat(float value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte getTypeId() {
|
||||
return TYPE_ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLong() {
|
||||
return (long) this.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInt() {
|
||||
return floor(this.value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getShort() {
|
||||
return (short)(floor(this.value) & 0xFFFF);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte getByte() {
|
||||
return (byte)(floor(this.value) & 0xFF);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getDouble() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getFloat() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "NBTFloat{" +
|
||||
"value=" + value +
|
||||
'}';
|
||||
}
|
||||
}
|
39
src/main/java/com/io/yutian/aulib/nbt/NBTHelper.java
Normal file
39
src/main/java/com/io/yutian/aulib/nbt/NBTHelper.java
Normal file
|
@ -0,0 +1,39 @@
|
|||
package com.io.yutian.aulib.nbt;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class NBTHelper {
|
||||
|
||||
@Nullable
|
||||
public static INBT convert(Object object) {
|
||||
if (object instanceof Byte) {
|
||||
return new NBTByte((byte) object);
|
||||
} else if (object instanceof Short) {
|
||||
return new NBTShort((short) object);
|
||||
} else if (object instanceof Integer) {
|
||||
return new NBTInt((int) object);
|
||||
} else if (object instanceof Long) {
|
||||
return new NBTLong((long) object);
|
||||
} else if (object instanceof Float) {
|
||||
return new NBTFloat((float) object);
|
||||
} else if (object instanceof Double) {
|
||||
return new NBTDouble((double) object);
|
||||
} else if (object instanceof byte[]) {
|
||||
return new NBTByteArray((byte[]) object);
|
||||
} else if (object instanceof String) {
|
||||
return new NBTString((String) object);
|
||||
} else if (object instanceof int[]) {
|
||||
return new NBTIntArray((int[]) object);
|
||||
} else if (object instanceof long[]) {
|
||||
return new NBTLongArray((long[]) object);
|
||||
} else if (object instanceof Boolean) {
|
||||
return new NBTByte((byte) ((boolean)object ? 1 : 0));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Object convertNMSNBT(INBT nbt) {
|
||||
return nbt.getNMSNBT();
|
||||
}
|
||||
|
||||
}
|
59
src/main/java/com/io/yutian/aulib/nbt/NBTInt.java
Normal file
59
src/main/java/com/io/yutian/aulib/nbt/NBTInt.java
Normal file
|
@ -0,0 +1,59 @@
|
|||
package com.io.yutian.aulib.nbt;
|
||||
|
||||
public class NBTInt extends NBTNumber {
|
||||
|
||||
public static byte TYPE_ID = 3;
|
||||
|
||||
private int value;
|
||||
|
||||
public NBTInt(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte getTypeId() {
|
||||
return TYPE_ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLong() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInt() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getShort() {
|
||||
return (short)(this.value & 0xFFFF);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte getByte() {
|
||||
return (byte)(this.value & 0xFF);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getDouble() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getFloat() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "NBTInt{" +
|
||||
"value=" + value +
|
||||
'}';
|
||||
}
|
||||
}
|
27
src/main/java/com/io/yutian/aulib/nbt/NBTIntArray.java
Normal file
27
src/main/java/com/io/yutian/aulib/nbt/NBTIntArray.java
Normal file
|
@ -0,0 +1,27 @@
|
|||
package com.io.yutian.aulib.nbt;
|
||||
|
||||
public class NBTIntArray extends INBT {
|
||||
|
||||
public static byte TYPE_ID = 11;
|
||||
|
||||
private int[] value;
|
||||
|
||||
public NBTIntArray(int[] value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public int[] getIntArray() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte getTypeId() {
|
||||
return TYPE_ID;
|
||||
}
|
||||
|
||||
}
|
61
src/main/java/com/io/yutian/aulib/nbt/NBTItemStack.java
Normal file
61
src/main/java/com/io/yutian/aulib/nbt/NBTItemStack.java
Normal file
|
@ -0,0 +1,61 @@
|
|||
package com.io.yutian.aulib.nbt;
|
||||
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import org.bukkit.craftbukkit.v1_18_R2.inventory.CraftItemStack;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class NBTItemStack {
|
||||
|
||||
private ItemStack originalItemStack;
|
||||
private net.minecraft.world.item.ItemStack nmsItemStack;
|
||||
|
||||
protected ItemStack resultItemStack;
|
||||
|
||||
public NBTItemStack(ItemStack itemStack) {
|
||||
this.originalItemStack = itemStack;
|
||||
this.nmsItemStack = CraftItemStack.asNMSCopy(itemStack);
|
||||
}
|
||||
|
||||
public NBTCompound getTag() {
|
||||
NBTTagCompound tag = nmsItemStack.u();
|
||||
if (tag == null) {
|
||||
tag = new NBTTagCompound();
|
||||
}
|
||||
return (NBTCompound) INBT.as(tag);
|
||||
}
|
||||
|
||||
public void editTag(Consumer<NBTCompound> consumer) {
|
||||
NBTCompound tag = getTag();
|
||||
consumer.accept(tag);
|
||||
setTag(tag);
|
||||
}
|
||||
|
||||
public void setTag(NBTCompound nbtCompound) {
|
||||
nmsItemStack.c((NBTTagCompound) INBT.asNMS(nbtCompound));
|
||||
resultItemStack = CraftItemStack.asBukkitCopy(nmsItemStack);
|
||||
}
|
||||
|
||||
public ItemStack getOriginalItemStack() {
|
||||
return originalItemStack;
|
||||
}
|
||||
|
||||
public ItemStack getItemStack() {
|
||||
return resultItemStack;
|
||||
}
|
||||
|
||||
public net.minecraft.world.item.ItemStack getNMSItemStack() {
|
||||
return nmsItemStack;
|
||||
}
|
||||
|
||||
public static NBTItemStack build(ItemStack itemStack) {
|
||||
return new NBTItemStack(itemStack);
|
||||
}
|
||||
|
||||
public static NBTItemStack build(NBTCompound nbtCompound) {
|
||||
net.minecraft.world.item.ItemStack nmsItemStack = net.minecraft.world.item.ItemStack.a((NBTTagCompound) INBT.asNMS(nbtCompound));
|
||||
return new NBTItemStack(CraftItemStack.asBukkitCopy(nmsItemStack));
|
||||
}
|
||||
|
||||
}
|
77
src/main/java/com/io/yutian/aulib/nbt/NBTList.java
Normal file
77
src/main/java/com/io/yutian/aulib/nbt/NBTList.java
Normal file
|
@ -0,0 +1,77 @@
|
|||
package com.io.yutian.aulib.nbt;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class NBTList<T extends INBT> extends INBT {
|
||||
|
||||
public static byte TYPE_ID = 9;
|
||||
|
||||
private List<T> value = new ArrayList<>();
|
||||
private byte type = 0;
|
||||
|
||||
public NBTList(List<T> value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public NBTList() {
|
||||
}
|
||||
|
||||
public List<T> getList() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return value.size();
|
||||
}
|
||||
|
||||
public T get(int index) {
|
||||
if (index > value.size()) {
|
||||
return null;
|
||||
}
|
||||
return value.get(index);
|
||||
}
|
||||
|
||||
public void add(T nbtBase) {
|
||||
if (nbtBase.getTypeId() == 0) {
|
||||
return;
|
||||
}
|
||||
if (this.type == 0) {
|
||||
this.type = nbtBase.getTypeId();
|
||||
} else if (this.type != nbtBase.getTypeId()) {
|
||||
return;
|
||||
}
|
||||
this.value.add(nbtBase);
|
||||
}
|
||||
|
||||
public void remove(int index) {
|
||||
this.value.remove(index);
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return value.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte getTypeId() {
|
||||
return TYPE_ID;
|
||||
}
|
||||
|
||||
public byte getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "NBTList{" +
|
||||
"value=" + value +
|
||||
", type=" + type +
|
||||
'}';
|
||||
}
|
||||
|
||||
}
|
62
src/main/java/com/io/yutian/aulib/nbt/NBTLong.java
Normal file
62
src/main/java/com/io/yutian/aulib/nbt/NBTLong.java
Normal file
|
@ -0,0 +1,62 @@
|
|||
package com.io.yutian.aulib.nbt;
|
||||
|
||||
public class NBTLong extends NBTNumber {
|
||||
|
||||
public static byte TYPE_ID = 4;
|
||||
|
||||
private long value;
|
||||
|
||||
public NBTLong(long value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public NBTLong() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte getTypeId() {
|
||||
return TYPE_ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLong() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInt() {
|
||||
return (int)(this.value & 0x7fffffffffffffffL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getShort() {
|
||||
return (short)(this.value & 0xFFFF);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte getByte() {
|
||||
return (byte)(this.value & 0xFF);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getDouble() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getFloat() {
|
||||
return (float) this.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "NBTLong{" +
|
||||
"value=" + value +
|
||||
'}';
|
||||
}
|
||||
}
|
27
src/main/java/com/io/yutian/aulib/nbt/NBTLongArray.java
Normal file
27
src/main/java/com/io/yutian/aulib/nbt/NBTLongArray.java
Normal file
|
@ -0,0 +1,27 @@
|
|||
package com.io.yutian.aulib.nbt;
|
||||
|
||||
public class NBTLongArray extends INBT {
|
||||
|
||||
public static byte TYPE_ID = 12;
|
||||
|
||||
private long[] value;
|
||||
|
||||
public NBTLongArray(long[] value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public long[] getLongArray() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte getTypeId() {
|
||||
return TYPE_ID;
|
||||
}
|
||||
|
||||
}
|
22
src/main/java/com/io/yutian/aulib/nbt/NBTNumber.java
Normal file
22
src/main/java/com/io/yutian/aulib/nbt/NBTNumber.java
Normal file
|
@ -0,0 +1,22 @@
|
|||
package com.io.yutian.aulib.nbt;
|
||||
|
||||
public abstract class NBTNumber implements INBT {
|
||||
|
||||
public abstract long getLong();
|
||||
|
||||
public abstract int getInt();
|
||||
|
||||
public abstract short getShort();
|
||||
|
||||
public abstract byte getByte();
|
||||
|
||||
public abstract double getDouble();
|
||||
|
||||
public abstract float getFloat();
|
||||
|
||||
public static int floor(double paramDouble) {
|
||||
int i = (int)paramDouble;
|
||||
return paramDouble < i ? i - 1 : i;
|
||||
}
|
||||
|
||||
}
|
62
src/main/java/com/io/yutian/aulib/nbt/NBTShort.java
Normal file
62
src/main/java/com/io/yutian/aulib/nbt/NBTShort.java
Normal file
|
@ -0,0 +1,62 @@
|
|||
package com.io.yutian.aulib.nbt;
|
||||
|
||||
public class NBTShort extends NBTNumber {
|
||||
|
||||
public static byte TYPE_ID = 2;
|
||||
|
||||
private short value;
|
||||
|
||||
public NBTShort(short value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public NBTShort() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte getTypeId() {
|
||||
return TYPE_ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLong() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInt() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getShort() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte getByte() {
|
||||
return (byte)(this.value & 0xFF);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getDouble() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getFloat() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "NBTShort{" +
|
||||
"value=" + value +
|
||||
'}';
|
||||
}
|
||||
}
|
36
src/main/java/com/io/yutian/aulib/nbt/NBTString.java
Normal file
36
src/main/java/com/io/yutian/aulib/nbt/NBTString.java
Normal file
|
@ -0,0 +1,36 @@
|
|||
package com.io.yutian.aulib.nbt;
|
||||
|
||||
public class NBTString extends INBT {
|
||||
|
||||
public static byte TYPE_ID = 8;
|
||||
|
||||
private String value;
|
||||
|
||||
public NBTString(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public NBTString() {
|
||||
}
|
||||
|
||||
public String getString() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte getTypeId() {
|
||||
return TYPE_ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "NBTString{" +
|
||||
"value='" + value + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
84
src/main/java/com/io/yutian/aulib/point/DirectionPoint.java
Normal file
84
src/main/java/com/io/yutian/aulib/point/DirectionPoint.java
Normal file
|
@ -0,0 +1,84 @@
|
|||
package com.io.yutian.aulib.point;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class DirectionPoint extends Point {
|
||||
|
||||
private float yaw;
|
||||
private float pitch;
|
||||
|
||||
public DirectionPoint(int x, int y, int z, float yaw, float pitch) {
|
||||
super(x, y, z);
|
||||
this.yaw = yaw;
|
||||
this.pitch = pitch;
|
||||
}
|
||||
|
||||
public DirectionPoint(double x, double y, double z) {
|
||||
this(x, y, z, 0f, 0f);
|
||||
}
|
||||
|
||||
public DirectionPoint(double x, double y, double z, float yaw, float pitch) {
|
||||
super(x, y, z);
|
||||
this.yaw = yaw;
|
||||
this.pitch = pitch;
|
||||
}
|
||||
|
||||
public float getPitch() {
|
||||
return pitch;
|
||||
}
|
||||
|
||||
public float getYaw() {
|
||||
return yaw;
|
||||
}
|
||||
|
||||
public void setYaw(float yaw) {
|
||||
this.yaw = yaw;
|
||||
}
|
||||
|
||||
public void setPitch(float pitch) {
|
||||
this.pitch = pitch;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Location toLocation(World world) {
|
||||
return new Location(world, getX(), getY(), getZ(), yaw, pitch);
|
||||
}
|
||||
|
||||
public static DirectionPoint of(Location location) {
|
||||
return new DirectionPoint(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DirectionPoint{" +
|
||||
"x=" + getX() +
|
||||
", y=" + getY() +
|
||||
", z=" + getZ() +
|
||||
", yaw=" + yaw +
|
||||
", pitch=" + pitch +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
if (!super.equals(o)) return false;
|
||||
DirectionPoint that = (DirectionPoint) o;
|
||||
return super.equals(o) && Float.compare(that.yaw, yaw) == 0 && Float.compare(that.pitch, pitch) == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(super.hashCode(), yaw, pitch);
|
||||
}
|
||||
|
||||
public static DirectionPoint deserialize(ConfigurationSection section) {
|
||||
return new DirectionPoint(section.getDouble("x"), section.getDouble("y"), section.getDouble("z"), (float) section.getDouble("yaw"), (float) section.getDouble("pitch"));
|
||||
}
|
||||
|
||||
}
|
101
src/main/java/com/io/yutian/aulib/point/Point.java
Normal file
101
src/main/java/com/io/yutian/aulib/point/Point.java
Normal file
|
@ -0,0 +1,101 @@
|
|||
package com.io.yutian.aulib.point;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class Point {
|
||||
|
||||
private double x;
|
||||
private double y;
|
||||
private double z;
|
||||
|
||||
public Point(int x, int y, int z) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
public Point(double x, double y, double z) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
public int getBlockX() {
|
||||
return (int) Math.floor(x);
|
||||
}
|
||||
|
||||
public int getBlockY() {
|
||||
return (int) Math.floor(y);
|
||||
}
|
||||
|
||||
public int getBlockZ() {
|
||||
return (int) Math.floor(z);
|
||||
}
|
||||
|
||||
public double getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public double getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
public double getZ() {
|
||||
return z;
|
||||
}
|
||||
|
||||
public void setX(double x) {
|
||||
this.x = x;
|
||||
}
|
||||
|
||||
public void setY(double y) {
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
public void setZ(double z) {
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
public Point clone() {
|
||||
return new Point(x, y, z);
|
||||
}
|
||||
|
||||
public Location toLocation(World world) {
|
||||
return new Location(world, x, y, z, 0, 0);
|
||||
}
|
||||
|
||||
public static Point of(Location location) {
|
||||
return new Point(location.getX(), location.getY(), location.getZ());
|
||||
}
|
||||
|
||||
public static Point deserialize(ConfigurationSection section) {
|
||||
return new Point(section.getDouble("x"), section.getDouble("y"), section.getDouble("z"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Point{" +
|
||||
"x=" + x +
|
||||
", y=" + y +
|
||||
", z=" + z +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Point point = (Point) o;
|
||||
return Double.compare(point.x, x) == 0 && Double.compare(point.y, y) == 0 && Double.compare(point.z, z) == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(x, y, z);
|
||||
}
|
||||
|
||||
}
|
51
src/main/java/com/io/yutian/aulib/point/Region.java
Normal file
51
src/main/java/com/io/yutian/aulib/point/Region.java
Normal file
|
@ -0,0 +1,51 @@
|
|||
package com.io.yutian.aulib.point;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
|
||||
public class Region {
|
||||
|
||||
private World world;
|
||||
private Point min;
|
||||
private Point max;
|
||||
|
||||
public Region(World world, Point min, Point max) {
|
||||
this.world = world;
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
}
|
||||
|
||||
public World getWorld() {
|
||||
return world;
|
||||
}
|
||||
|
||||
public Point getMin() {
|
||||
return min;
|
||||
}
|
||||
|
||||
public Point getMax() {
|
||||
return max;
|
||||
}
|
||||
|
||||
public static Region deserialize(ConfigurationSection section) {
|
||||
World world1 = Bukkit.getWorld(section.getString("world"));
|
||||
Point point1 = Point.deserialize(section.getConfigurationSection("min"));
|
||||
Point point2 = Point.deserialize(section.getConfigurationSection("max"));
|
||||
return new Region(world1, point1, point2);
|
||||
}
|
||||
|
||||
public boolean isInRegion(Location location) {
|
||||
if (!location.getWorld().getName().equalsIgnoreCase(world.getName())) {
|
||||
return false;
|
||||
}
|
||||
return (location.getBlockX() >= this.min.getX()
|
||||
&& location.getBlockX() <= this.max.getX()
|
||||
&& location.getBlockY() >= this.min.getY()
|
||||
&& location.getBlockY() <= this.max.getY()
|
||||
&& location.getBlockZ() >= this.min.getZ()
|
||||
&& location.getBlockZ() <= this.max.getZ());
|
||||
}
|
||||
|
||||
}
|
65
src/main/java/com/io/yutian/aulib/util/AESUtil.java
Normal file
65
src/main/java/com/io/yutian/aulib/util/AESUtil.java
Normal file
|
@ -0,0 +1,65 @@
|
|||
package com.io.yutian.aulib.util;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.KeyGenerator;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Base64;
|
||||
|
||||
public class AESUtil {
|
||||
|
||||
private static final String KEY_ALGORITHM = "AES";
|
||||
private static final String DEFAULT_CIPHER_ALGORITHM = "AES/ECB/PKCS5Padding";
|
||||
|
||||
public static String getAESRandomKey() {
|
||||
SecureRandom random = new SecureRandom();
|
||||
long randomKey = random.nextLong();
|
||||
return String.valueOf(randomKey);
|
||||
}
|
||||
|
||||
public static String encrypt(String content, String key) {
|
||||
try {
|
||||
Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);
|
||||
byte[] byteContent = content.getBytes("utf-8");
|
||||
cipher.init(Cipher.ENCRYPT_MODE, getSecretKey(key));
|
||||
byte[] result = cipher.doFinal(byteContent);
|
||||
return byte2Base64(result);
|
||||
} catch (Exception ex) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String decrypt(String content, String key) {
|
||||
try {
|
||||
Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);
|
||||
cipher.init(Cipher.DECRYPT_MODE, getSecretKey(key));
|
||||
byte[] result = cipher.doFinal(base642Byte(content));
|
||||
return new String(result, "utf-8");
|
||||
} catch (Exception ex) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static SecretKeySpec getSecretKey(final String key) {
|
||||
try {
|
||||
KeyGenerator kg = KeyGenerator.getInstance(KEY_ALGORITHM);
|
||||
SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
|
||||
random.setSeed(key.getBytes());
|
||||
kg.init(128, random);
|
||||
SecretKey secretKey = kg.generateKey();
|
||||
return new SecretKeySpec(secretKey.getEncoded(), KEY_ALGORITHM);
|
||||
} catch (NoSuchAlgorithmException ex) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static String byte2Base64(byte[] bytes) {
|
||||
return Base64.getEncoder().encodeToString(bytes);
|
||||
}
|
||||
|
||||
private static byte[] base642Byte(String base64Key) {
|
||||
return Base64.getDecoder().decode(base64Key);
|
||||
}
|
||||
}
|
54
src/main/java/com/io/yutian/aulib/util/ClassUtil.java
Normal file
54
src/main/java/com/io/yutian/aulib/util/ClassUtil.java
Normal file
|
@ -0,0 +1,54 @@
|
|||
package com.io.yutian.aulib.util;
|
||||
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class ClassUtil {
|
||||
|
||||
public static boolean isAssignableFrom(Object object, Class clazz) {
|
||||
if (object == null) {
|
||||
return false;
|
||||
}
|
||||
Class c = PRIMITIVE_TO_WRAPPER.getOrDefault(clazz, clazz);
|
||||
if (c.isAssignableFrom(object.getClass())) {
|
||||
return true;
|
||||
}
|
||||
if (object.getClass().equals(Integer.class)) {
|
||||
if (c.equals(Double.class) || c.equals(Float.class) || c.equals(Long.class)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (object.getClass().equals(String.class)) {
|
||||
String s = (String) object;
|
||||
if (c.equals(Double.class)) {
|
||||
return StringUtil.isDouble(s);
|
||||
} else if (c.equals(Float.class)) {
|
||||
return StringUtil.isFloat(s);
|
||||
} else if (c.equals(Long.class)) {
|
||||
return StringUtil.isLong(s);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static String getJar(Plugin plugin) {
|
||||
String p = plugin.getClass().getProtectionDomain().getCodeSource().getLocation().getPath();
|
||||
return p.substring(1);
|
||||
}
|
||||
|
||||
public static final Map<Class<?>, Class<?>> PRIMITIVE_TO_WRAPPER = new HashMap<>();
|
||||
|
||||
static {
|
||||
PRIMITIVE_TO_WRAPPER.put(boolean.class, Boolean.class);
|
||||
PRIMITIVE_TO_WRAPPER.put(byte.class, Byte.class);
|
||||
PRIMITIVE_TO_WRAPPER.put(short.class, Short.class);
|
||||
PRIMITIVE_TO_WRAPPER.put(char.class, Character.class);
|
||||
PRIMITIVE_TO_WRAPPER.put(int.class, Integer.class);
|
||||
PRIMITIVE_TO_WRAPPER.put(long.class, Long.class);
|
||||
PRIMITIVE_TO_WRAPPER.put(float.class, Float.class);
|
||||
PRIMITIVE_TO_WRAPPER.put(double.class, Double.class);
|
||||
}
|
||||
|
||||
}
|
47
src/main/java/com/io/yutian/aulib/util/ComponentBuilder.java
Normal file
47
src/main/java/com/io/yutian/aulib/util/ComponentBuilder.java
Normal file
|
@ -0,0 +1,47 @@
|
|||
package com.io.yutian.aulib.util;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.event.ClickEvent;
|
||||
import net.kyori.adventure.text.event.HoverEvent;
|
||||
|
||||
public class ComponentBuilder {
|
||||
|
||||
private Component component;
|
||||
|
||||
public ComponentBuilder() {
|
||||
component = Component.text("");
|
||||
}
|
||||
|
||||
public ComponentBuilder add(Component component) {
|
||||
component.append(component);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ComponentBuilder add(String text) {
|
||||
return add(Component.text(text));
|
||||
}
|
||||
|
||||
public ComponentBuilder add(String text, ClickEvent clickEvent) {
|
||||
Component component1 = Component.text(text);
|
||||
component1.clickEvent(clickEvent);
|
||||
return add(component1);
|
||||
}
|
||||
|
||||
public ComponentBuilder add(String text, ClickEvent clickEvent, HoverEvent hoverEvent) {
|
||||
Component component1 = Component.text(text);
|
||||
component.clickEvent(clickEvent);
|
||||
component.hoverEvent(hoverEvent);
|
||||
return add(component1);
|
||||
}
|
||||
|
||||
public ComponentBuilder add(String text, HoverEvent hoverEvent) {
|
||||
Component component1 = Component.text(text);
|
||||
component.hoverEvent(hoverEvent);
|
||||
return add(component1);
|
||||
}
|
||||
|
||||
public Component build() {
|
||||
return component;
|
||||
}
|
||||
|
||||
}
|
40
src/main/java/com/io/yutian/aulib/util/EntityUtil.java
Normal file
40
src/main/java/com/io/yutian/aulib/util/EntityUtil.java
Normal file
|
@ -0,0 +1,40 @@
|
|||
package com.io.yutian.aulib.util;
|
||||
|
||||
import com.google.common.base.Charsets;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.attribute.Attribute;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class EntityUtil {
|
||||
|
||||
public static Entity getEntity(World world, UUID uuid) {
|
||||
for (Entity entity : world.getEntities()) {
|
||||
if (entity.getUniqueId().equals(uuid)) {
|
||||
return entity;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static UUID getPlayerUniqueId(String name) {
|
||||
Player player = Bukkit.getPlayerExact(name);
|
||||
if (player != null) {
|
||||
return player.getUniqueId();
|
||||
}
|
||||
GameProfile profile = new GameProfile(UUID.nameUUIDFromBytes(("OfflinePlayer:" + name).getBytes(Charsets.UTF_8)), name);
|
||||
return profile != null ? profile.getId() : null;
|
||||
}
|
||||
|
||||
public static void recoverHealth(LivingEntity livingEntity, double value) {
|
||||
if (value > 0.0) {
|
||||
livingEntity.setHealth(Math.min(livingEntity.getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue(), livingEntity.getHealth() + value));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
102
src/main/java/com/io/yutian/aulib/util/FileUtil.java
Normal file
102
src/main/java/com/io/yutian/aulib/util/FileUtil.java
Normal file
|
@ -0,0 +1,102 @@
|
|||
package com.io.yutian.aulib.util;
|
||||
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class FileUtil {
|
||||
|
||||
public static List<File> getFilesForFolder(File folder) {
|
||||
List<File> files = new ArrayList<>();
|
||||
if (!folder.isDirectory()) {
|
||||
throw new IllegalArgumentException("File \"" + folder.getName() + "\" is not a directory");
|
||||
}
|
||||
File[] listFiles = folder.listFiles();
|
||||
for (File file : listFiles) {
|
||||
if (file.isDirectory()) {
|
||||
files.addAll(getFilesForFolder(file));
|
||||
} else {
|
||||
files.add(file);
|
||||
}
|
||||
}
|
||||
return files;
|
||||
}
|
||||
|
||||
public static List<File> getSubFolders(File folder) {
|
||||
List<File> subFolders = new ArrayList<>();
|
||||
if (!folder.isDirectory()) {
|
||||
throw new IllegalArgumentException("File \"" + folder.getName() + "\" is not a directory");
|
||||
}
|
||||
File[] listFiles = folder.listFiles();
|
||||
for (File file : listFiles) {
|
||||
if (file.isDirectory()) {
|
||||
subFolders.add(file);
|
||||
}
|
||||
}
|
||||
return subFolders;
|
||||
}
|
||||
|
||||
public static void copy(File inFile, File outFile) {
|
||||
if (inFile.isDirectory()) {
|
||||
copyDir(inFile, outFile, new String[0]);
|
||||
} else {
|
||||
copyFile(inFile, outFile);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean copyFile(File inFile, File outFile) {
|
||||
return org.bukkit.util.FileUtil.copy(inFile, outFile);
|
||||
}
|
||||
|
||||
public static void copyDir(File inDir, File outDir, String... exclude) {
|
||||
if (!outDir.exists()) {
|
||||
outDir.mkdir();
|
||||
}
|
||||
String[] list = inDir.list();
|
||||
for (String p : list) {
|
||||
if (!Arrays.asList(exclude).contains(p)) {
|
||||
copy(new File(inDir, p), new File(outDir, p));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean removeDir(File dir) {
|
||||
if (dir.isDirectory()) {
|
||||
for (File f : dir.listFiles()) {
|
||||
if (!removeDir(f)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return dir.delete();
|
||||
}
|
||||
|
||||
public static FileOutputStream getOutputStream(File file) {
|
||||
try {
|
||||
return new FileOutputStream(file);
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static FileInputStream getInputStream(File file) {
|
||||
try {
|
||||
return new FileInputStream(file);
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static File getFile(Plugin plugin, String path, String fileName) {
|
||||
File p = (path == null || path.equals("")) ? plugin.getDataFolder() : new File(plugin.getDataFolder() + File.separator + path);
|
||||
if (!p.exists()) {
|
||||
p.mkdirs();
|
||||
}
|
||||
File file = new File(p + File.separator + fileName);
|
||||
return file;
|
||||
}
|
||||
|
||||
}
|
364
src/main/java/com/io/yutian/aulib/util/ItemStackBuilder.java
Normal file
364
src/main/java/com/io/yutian/aulib/util/ItemStackBuilder.java
Normal file
|
@ -0,0 +1,364 @@
|
|||
package com.io.yutian.aulib.util;
|
||||
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import com.mojang.authlib.properties.Property;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.block.banner.Pattern;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
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.potion.PotionEffect;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.*;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public int getAmount() {
|
||||
return amount;
|
||||
}
|
||||
|
||||
public Material getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public List<String> getLore() {
|
||||
return lore;
|
||||
}
|
||||
|
||||
public int getCustomModelData() {
|
||||
return customModelData;
|
||||
}
|
||||
|
||||
public Map<Enchantment, Integer> getEnchants() {
|
||||
return enchants;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public ItemStackBuilder setItemStack(ItemStack item) {
|
||||
this.itemStack = item;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackBuilder setType(Material type) {
|
||||
this.type = type;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackBuilder setCustomModelData(int customModelData) {
|
||||
this.customModelData = 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;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackBuilder setDisplayName(String name) {
|
||||
this.displayName = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackBuilder setLore(List<String> loreList) {
|
||||
this.lore = loreList;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackBuilder setLore(String... lores) {
|
||||
this.lore = new ArrayList<String>(Arrays.asList(lores));
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackBuilder addLore(String lore) {
|
||||
this.lore.add(lore);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackBuilder addLore(String... lores) {
|
||||
this.lore.addAll(Arrays.asList(lores));
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackBuilder addLore(List<String> lores) {
|
||||
for (String lore : lores) {
|
||||
this.lore.add(lore);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackBuilder addEnchant(Enchantment ench, int level) {
|
||||
this.enchants.put(ench, level);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackBuilder removeEnchant(Enchantment ench) {
|
||||
this.enchants.remove(ench);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackBuilder setEnchants(Map<Enchantment, Integer> enchants) {
|
||||
this.enchants = enchants;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackBuilder setEnchants(List<String> enchants) {
|
||||
this.enchants = getEnchantsFromList(enchants);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackBuilder setItemFlags(Set<ItemFlag> itemFlags) {
|
||||
this.itemFlags = itemFlags;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackBuilder addItemFlags(ItemFlag[] itemFlags) {
|
||||
this.itemFlags.addAll(Arrays.asList(itemFlags));
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackBuilder addItemFlags(ItemFlag itemFlag) {
|
||||
this.itemFlags.add(itemFlag);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackBuilder addPotionEffect(PotionEffect potionEffect) {
|
||||
this.potionEffects.add(potionEffect);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackBuilder addPattern(Pattern pattern) {
|
||||
this.patterns.add(pattern);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackBuilder addFireworkEffect(FireworkEffect fireworkEffect) {
|
||||
this.fireworkEffects.add(fireworkEffect);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackBuilder setSkullTextures(String skullTextures) {
|
||||
this.skullTextures = skullTextures;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackBuilder setSkullOwner(UUID skullOwner) {
|
||||
this.skullOwner = skullOwner;
|
||||
return this;
|
||||
}
|
||||
|
||||
protected Map<Enchantment, Integer> getEnchantsFromList(List<String> enchants) {
|
||||
Map<Enchantment, Integer> map = new HashMap<>();
|
||||
if (enchants == null) {
|
||||
return map;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
protected static ItemStack setEnchants(ItemStack stack, List<String> enchants) {
|
||||
if (enchants == null) {
|
||||
return stack;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
private void setField(Object instance, String name, Object value) throws ReflectiveOperationException {
|
||||
Field field = instance.getClass().getDeclaredField(name);
|
||||
field.setAccessible(true);
|
||||
field.set(instance, value);
|
||||
}
|
||||
|
||||
}
|
29
src/main/java/com/io/yutian/aulib/util/MathUtil.java
Normal file
29
src/main/java/com/io/yutian/aulib/util/MathUtil.java
Normal file
|
@ -0,0 +1,29 @@
|
|||
package com.io.yutian.aulib.util;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
|
||||
public class MathUtil {
|
||||
|
||||
public static double round(double d) {
|
||||
return new BigDecimal(Double.toString(d)).setScale(2, RoundingMode.HALF_UP).doubleValue();
|
||||
}
|
||||
|
||||
public static double round(double d, int scale) {
|
||||
return new BigDecimal(Double.toString(d)).setScale(scale, RoundingMode.HALF_UP).doubleValue();
|
||||
}
|
||||
|
||||
public static int clamp(int value, int min, int max) {
|
||||
return Math.max(min, Math.min(max, value));
|
||||
}
|
||||
|
||||
public static double clamp(double value, double min, double max) {
|
||||
return Math.max(min, Math.min(max, value));
|
||||
}
|
||||
|
||||
public static float clamp(float value, float min, float max) {
|
||||
return Math.max(min, Math.min(max, value));
|
||||
}
|
||||
|
||||
|
||||
}
|
76
src/main/java/com/io/yutian/aulib/util/MojongAPI.java
Normal file
76
src/main/java/com/io/yutian/aulib/util/MojongAPI.java
Normal file
|
@ -0,0 +1,76 @@
|
|||
package com.io.yutian.aulib.util;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.util.UUID;
|
||||
|
||||
public class MojongAPI {
|
||||
|
||||
public static final String uuidURL = "https://sessionserver.mojang.com/session/minecraft/profile/";
|
||||
public static final String nameURL = "https://api.mojang.com/users/profiles/minecraft/";
|
||||
|
||||
public static JSONObject getPlayerJSON(UUID uuid, String name) throws IOException {
|
||||
URL url;
|
||||
|
||||
if (name != null) {
|
||||
url = new URL(nameURL + name);
|
||||
} else {
|
||||
url = new URL(uuidURL + uuid);
|
||||
}
|
||||
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||
connection.setUseCaches(false);
|
||||
connection.setInstanceFollowRedirects(true);
|
||||
connection.setDoOutput(true);
|
||||
connection.setDoInput(true);
|
||||
connection.setRequestMethod("GET");
|
||||
|
||||
BufferedReader bufferedReader = new BufferedReader(
|
||||
new InputStreamReader(connection.getInputStream()));
|
||||
String line;
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
while ((line = bufferedReader.readLine()) != null) {
|
||||
stringBuilder.append(line);
|
||||
}
|
||||
bufferedReader.close();
|
||||
if (!stringBuilder.toString().startsWith("{")) {
|
||||
return null;
|
||||
}
|
||||
return new JSONObject(stringBuilder.toString());
|
||||
}
|
||||
|
||||
public static UUID getUUID(String name) {
|
||||
try {
|
||||
String uuidTemp = getPlayerJSON(null, name).getString("id");
|
||||
String uuid = "";
|
||||
for (int i = 0; i <= 31; i++) {
|
||||
uuid = uuid + uuidTemp.charAt(i);
|
||||
if (i == 7 || i == 11 || i == 15 || i == 19) {
|
||||
uuid = uuid + "-";
|
||||
}
|
||||
}
|
||||
if (getPlayerJSON(null, name) != null) {
|
||||
return UUID.fromString(uuid);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String getName(UUID uuid) {
|
||||
try {
|
||||
if (getPlayerJSON(uuid, null) != null) {
|
||||
return getPlayerJSON(uuid, null).getString("name");
|
||||
}
|
||||
return null;
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
package com.io.yutian.aulib.util;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Item;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class PlayerInventoryUtil {
|
||||
|
||||
public static void giveItemStack(Player player, ItemStack itemStack) {
|
||||
if (PlayerInventoryUtil.hasFreeSlot(player)) {
|
||||
player.getInventory().addItem(itemStack);
|
||||
} else {
|
||||
Item item = player.getLocation().getWorld().dropItem(player.getLocation(), itemStack);
|
||||
item.setOwner(player.getUniqueId());
|
||||
item.setThrower(player.getUniqueId());
|
||||
item.setPickupDelay(20);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean hasItemStack(Player player, Predicate<ItemStack> predicate) {
|
||||
return hasItemStack(player, predicate, 1);
|
||||
}
|
||||
|
||||
public static boolean hasItemStack(Player player, Predicate<ItemStack> predicate, int amount) {
|
||||
int index = -1;
|
||||
int a = 0;
|
||||
while (index < 35) {
|
||||
index++;
|
||||
ItemStack i = player.getInventory().getItem(index);
|
||||
if (i == null) {
|
||||
continue;
|
||||
}
|
||||
if (predicate.test(i)) {
|
||||
a += i.getAmount();
|
||||
}
|
||||
}
|
||||
return a >= amount;
|
||||
}
|
||||
|
||||
public static void takeItemStack(Player player, Predicate<ItemStack> predicate) {
|
||||
takeItemStack(player, predicate, 1);
|
||||
}
|
||||
|
||||
public static void takeItemStack(Player player, Predicate<ItemStack> predicate, int amount) {
|
||||
int index = -1;
|
||||
int a = amount;
|
||||
while (index < 35) {
|
||||
if (a <= 0) {
|
||||
break;
|
||||
}
|
||||
index++;
|
||||
ItemStack i = player.getInventory().getItem(index);
|
||||
if (i == null) {
|
||||
continue;
|
||||
}
|
||||
if (predicate.test(i)) {
|
||||
int k = i.getAmount();
|
||||
if (k < a) {
|
||||
i.setType(Material.AIR);
|
||||
} else {
|
||||
int l = k - a;
|
||||
i.setAmount(l);
|
||||
}
|
||||
a -= k;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean hasFreeSlot(Player player) {
|
||||
return getFreeSize(player) > 0;
|
||||
}
|
||||
|
||||
public static int getFreeSize(Player player) {
|
||||
int index = -1;
|
||||
int freesize = 0;
|
||||
while (index < 35) {
|
||||
index++;
|
||||
ItemStack i = player.getInventory().getItem(index);
|
||||
if (i == null) {
|
||||
freesize++;
|
||||
continue;
|
||||
}
|
||||
if (i.getType().equals(Material.AIR)) {
|
||||
freesize++;
|
||||
}
|
||||
}
|
||||
return freesize;
|
||||
}
|
||||
|
||||
}
|
80
src/main/java/com/io/yutian/aulib/util/RandomBuilder.java
Normal file
80
src/main/java/com/io/yutian/aulib/util/RandomBuilder.java
Normal file
|
@ -0,0 +1,80 @@
|
|||
package com.io.yutian.aulib.util;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class RandomBuilder<T> {
|
||||
|
||||
private Map<T, Double> valueMap;
|
||||
|
||||
private List<Element> elementList = new ArrayList<>();
|
||||
private double maxElement = 0;
|
||||
|
||||
public RandomBuilder(Map<T, Double> map) {
|
||||
valueMap = map;
|
||||
|
||||
double minElement = 0;
|
||||
|
||||
for (Map.Entry<T, Double> entry : map.entrySet()) {
|
||||
minElement = maxElement;
|
||||
maxElement += entry.getValue();
|
||||
elementList.add(new Element(entry.getKey(), minElement, maxElement));
|
||||
}
|
||||
}
|
||||
|
||||
public T random() {
|
||||
return random(new Random());
|
||||
}
|
||||
|
||||
public T random(Random random) {
|
||||
double d = random.nextDouble() * maxElement;
|
||||
if (d == 0) {
|
||||
d = 0.1 * maxElement;
|
||||
}
|
||||
int size = valueMap.size();
|
||||
for (int i = 0; i < elementList.size(); i++) {
|
||||
Element element = elementList.get(i);
|
||||
if (element.isContainKey(d)) {
|
||||
return element.getValue();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public double getMaxElement() {
|
||||
return maxElement;
|
||||
}
|
||||
|
||||
public List<Element> getElementList() {
|
||||
return elementList;
|
||||
}
|
||||
|
||||
public Map<T, Double> getValueMap() {
|
||||
return valueMap;
|
||||
}
|
||||
|
||||
private class Element {
|
||||
|
||||
private T value;
|
||||
|
||||
private final double minElement;
|
||||
private final double maxElement;
|
||||
|
||||
public Element(T value, double element0, double element1) {
|
||||
this.value = value;
|
||||
this.minElement = Math.min(element0, element1);
|
||||
this.maxElement = Math.max(element0, element1);
|
||||
}
|
||||
|
||||
public T getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public boolean isContainKey(double element) {
|
||||
return element > minElement && element <= maxElement;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
59
src/main/java/com/io/yutian/aulib/util/RandomUtil.java
Normal file
59
src/main/java/com/io/yutian/aulib/util/RandomUtil.java
Normal file
|
@ -0,0 +1,59 @@
|
|||
package com.io.yutian.aulib.util;
|
||||
|
||||
import org.bukkit.Color;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
public class RandomUtil {
|
||||
|
||||
public static boolean random(double d) {
|
||||
return d >= new Random().nextFloat();
|
||||
}
|
||||
|
||||
public static Color getRandomColor() {
|
||||
Random random = new Random();
|
||||
int r = random.nextInt(256);
|
||||
int g = random.nextInt(256);
|
||||
int b = random.nextInt(256);
|
||||
return Color.fromRGB(r, g, b);
|
||||
}
|
||||
|
||||
public static Location getRandomLocation(World world, double minX, double maxX, double minZ, double maxZ) {
|
||||
double rx = getRandomDouble(minX, maxX, 3);
|
||||
double rz = getRandomDouble(minZ, maxZ, 3);
|
||||
int y = world.getHighestBlockAt((int)rx, (int)rz).getY()+1;
|
||||
Location location = new Location(world, rx, y, rz);
|
||||
return location;
|
||||
}
|
||||
|
||||
public static <E> E getRandomElement(List<E> list) {
|
||||
if (list.size() == 0) {
|
||||
return null;
|
||||
}
|
||||
return list.get(getRandomInt(0, list.size()-1));
|
||||
}
|
||||
|
||||
public static String getRandomString(String[] array) {
|
||||
Random r = new Random();
|
||||
return array[getRandomInt(0, array.length)];
|
||||
}
|
||||
|
||||
public static int getRandomInt(int min, int max) {
|
||||
if (min == max) {
|
||||
return max;
|
||||
}
|
||||
Random r = new Random();
|
||||
int i = min < max ? min : max;
|
||||
int a = min < max ? max : min;
|
||||
return r.nextInt(a - i + 1) + i;
|
||||
}
|
||||
|
||||
public static double getRandomDouble(double min, double max, int scl) {
|
||||
int pow = (int) Math.pow(10, scl);
|
||||
return Math.floor((Math.random() * (max - min) + min) * pow) / pow;
|
||||
}
|
||||
|
||||
}
|
170
src/main/java/com/io/yutian/aulib/util/ReflectionUtil.java
Normal file
170
src/main/java/com/io/yutian/aulib/util/ReflectionUtil.java
Normal file
|
@ -0,0 +1,170 @@
|
|||
package com.io.yutian.aulib.util;
|
||||
|
||||
import sun.misc.Unsafe;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
|
||||
public class ReflectionUtil {
|
||||
|
||||
public static Field getDeclaredField(Class clazz, String fieldName) {
|
||||
try {
|
||||
return clazz.getDeclaredField(fieldName);
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static Field getDeclaredField(Object object, String fieldName) {
|
||||
Field field = null;
|
||||
Class<?> clazz = object.getClass();
|
||||
for (;clazz != Object.class; clazz = clazz.getSuperclass()) {
|
||||
try {
|
||||
field = clazz.getDeclaredField(fieldName);
|
||||
return field;
|
||||
} catch (NoSuchFieldException e) {
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Object getFieldValue(Class clazz, Object object, String fieldName) {
|
||||
try {
|
||||
Field field = clazz.getDeclaredField(fieldName);
|
||||
field.setAccessible(true);
|
||||
return field.get(object);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static Object getFieldValue(Object object, String fieldName) {
|
||||
try {
|
||||
Class clazz = object.getClass();
|
||||
Field field = clazz.getDeclaredField(fieldName);
|
||||
field.setAccessible(true);
|
||||
return field.get(object);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static void setField(Class clazz, Object object, String fieldName, Object value) {
|
||||
try {
|
||||
Field field = clazz.getDeclaredField(fieldName);
|
||||
setField(object, value, field);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void setField(Object object, String fieldName, Object value) {
|
||||
try {
|
||||
Class clazz = object.getClass();
|
||||
Field field = clazz.getDeclaredField(fieldName);
|
||||
setField(object, value, field);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void setField(Object object, Object value, Field foundField) {
|
||||
boolean isStatic = (foundField.getModifiers() & Modifier.STATIC) == Modifier.STATIC;
|
||||
if (isStatic) {
|
||||
setStaticFieldUsingUnsafe(foundField, value);
|
||||
} else {
|
||||
setFieldUsingUnsafe(foundField, object, value);
|
||||
}
|
||||
}
|
||||
|
||||
public static void setStaticFieldUsingUnsafe(final Field field, final Object newValue) {
|
||||
try {
|
||||
field.setAccessible(true);
|
||||
int fieldModifiersMask = field.getModifiers();
|
||||
boolean isFinalModifierPresent = (fieldModifiersMask & Modifier.FINAL) == Modifier.FINAL;
|
||||
if (isFinalModifierPresent) {
|
||||
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
|
||||
try {
|
||||
Unsafe unsafe = getUnsafe();
|
||||
long offset = unsafe.staticFieldOffset(field);
|
||||
Object base = unsafe.staticFieldBase(field);
|
||||
setFieldUsingUnsafe(base, field.getType(), offset, newValue, unsafe);
|
||||
return null;
|
||||
} catch (Throwable t) {
|
||||
throw new RuntimeException(t);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
field.set(null, newValue);
|
||||
}
|
||||
} catch (SecurityException | IllegalAccessException | IllegalArgumentException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static void setFieldUsingUnsafe(final Field field, final Object object, final Object newValue) {
|
||||
try {
|
||||
field.setAccessible(true);
|
||||
int fieldModifiersMask = field.getModifiers();
|
||||
boolean isFinalModifierPresent = (fieldModifiersMask & Modifier.FINAL) == Modifier.FINAL;
|
||||
if (isFinalModifierPresent) {
|
||||
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
|
||||
try {
|
||||
Unsafe unsafe = getUnsafe();
|
||||
long offset = unsafe.objectFieldOffset(field);
|
||||
setFieldUsingUnsafe(object, field.getType(), offset, newValue, unsafe);
|
||||
return null;
|
||||
} catch (Throwable t) {
|
||||
throw new RuntimeException(t);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
try {
|
||||
field.set(object, newValue);
|
||||
} catch (IllegalAccessException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
} catch (SecurityException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static Unsafe getUnsafe() {
|
||||
try {
|
||||
Field field = Unsafe.class.getDeclaredField("theUnsafe");
|
||||
field.setAccessible(true);
|
||||
return (Unsafe) field.get(null);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static void setFieldUsingUnsafe(Object base, Class type, long offset, Object newValue, Unsafe unsafe) {
|
||||
if (type == Integer.TYPE) {
|
||||
unsafe.putInt(base, offset, ((Integer) newValue));
|
||||
} else if (type == Short.TYPE) {
|
||||
unsafe.putShort(base, offset, ((Short) newValue));
|
||||
} else if (type == Long.TYPE) {
|
||||
unsafe.putLong(base, offset, ((Long) newValue));
|
||||
} else if (type == Byte.TYPE) {
|
||||
unsafe.putByte(base, offset, ((Byte) newValue));
|
||||
} else if (type == Boolean.TYPE) {
|
||||
unsafe.putBoolean(base, offset, ((Boolean) newValue));
|
||||
} else if (type == Float.TYPE) {
|
||||
unsafe.putFloat(base, offset, ((Float) newValue));
|
||||
} else if (type == Double.TYPE) {
|
||||
unsafe.putDouble(base, offset, ((Double) newValue));
|
||||
} else if (type == Character.TYPE) {
|
||||
unsafe.putChar(base, offset, ((Character) newValue));
|
||||
} else {
|
||||
unsafe.putObject(base, offset, newValue);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
267
src/main/java/com/io/yutian/aulib/util/StringUtil.java
Normal file
267
src/main/java/com/io/yutian/aulib/util/StringUtil.java
Normal file
|
@ -0,0 +1,267 @@
|
|||
package com.io.yutian.aulib.util;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class StringUtil {
|
||||
|
||||
public static byte[] parseByteArray(String string) {
|
||||
String[] array = string.split(";");
|
||||
byte[] bytes = new byte[array.length];
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
String s = array[i];
|
||||
if (isByte(s)) {
|
||||
bytes[i] = Byte.parseByte(s);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
public static int[] parseIntArray(String string) {
|
||||
String[] array = string.split(";");
|
||||
int[] ints = new int[array.length];
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
String s = array[i];
|
||||
if (isInt(s)) {
|
||||
ints[i] = Integer.parseInt(s);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return ints;
|
||||
}
|
||||
|
||||
public static List<String> getStringContainData(String str, String start, String end) {
|
||||
List<String> result = new ArrayList<>();
|
||||
String regex = start + "(.*?)" + end;
|
||||
Pattern pattern = Pattern.compile(regex);
|
||||
Matcher matcher = pattern.matcher(str);
|
||||
while(matcher.find()){
|
||||
String key = matcher.group(matcher.groupCount());
|
||||
if(!key.contains(start) && !key.contains(end)){
|
||||
result.add(key);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static boolean isByte(String arg0) {
|
||||
try {
|
||||
Byte.valueOf(arg0);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isBoolean(String arg0) {
|
||||
try {
|
||||
if (arg0.equalsIgnoreCase("true") || arg0.equalsIgnoreCase("false")) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isDouble(String arg0) {
|
||||
try {
|
||||
Double.valueOf(arg0);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isFloat(String arg0) {
|
||||
try {
|
||||
Float.valueOf(arg0);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isInt(String arg0) {
|
||||
try {
|
||||
Integer.valueOf(arg0);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isLong(String arg0) {
|
||||
try {
|
||||
Long.valueOf(arg0);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isEnum(String arg0, Class<? extends Enum> enumType) {
|
||||
try {
|
||||
Enum.valueOf(enumType, arg0);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isUUID(String arg0) {
|
||||
try {
|
||||
UUID.fromString(arg0);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static String[] splitSpace(String arg0) {
|
||||
return arg0.split(" ");
|
||||
}
|
||||
|
||||
public static Object getRegexValue(String key, String lore) {
|
||||
if (key == null || lore == null) {
|
||||
return null;
|
||||
}
|
||||
String s = lore.contains(":") ? ":" : ":";
|
||||
if (lore.contains(s) && lore.contains(key)) {
|
||||
Pattern p = Pattern.compile("[^"+key+s+"]+");
|
||||
Matcher m = p.matcher(lore);
|
||||
try {
|
||||
m.find();
|
||||
if (m.group() != null) {
|
||||
return (Object) m.group();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static UUID getUUIDFromString(String s) {
|
||||
String md5 = getMD5(s);
|
||||
String uuid = md5.substring(0, 8) + "-" + md5.substring(8, 12) + "-" + md5.substring(12, 16) + "-" + md5.substring(16, 20) + "-" + md5.substring(20);
|
||||
|
||||
return UUID.fromString(uuid);
|
||||
}
|
||||
|
||||
public static String getMD5(String input) {
|
||||
try {
|
||||
MessageDigest md = MessageDigest.getInstance("MD5");
|
||||
byte[] messageDigest = md.digest(input.getBytes());
|
||||
BigInteger number = new BigInteger(1, messageDigest);
|
||||
String hashtext;
|
||||
for (hashtext = number.toString(16); hashtext.length() < 32; hashtext = "0" + hashtext) {}
|
||||
return hashtext;
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static String convertRGBToHex(int r, int g, int b) {
|
||||
String rFString, rSString, gFString, gSString,
|
||||
bFString, bSString, result;
|
||||
int red, green, blue;
|
||||
int rred, rgreen, rblue;
|
||||
red = r / 16;
|
||||
rred = r % 16;
|
||||
if (red == 10) rFString = "A";
|
||||
else if (red == 11) rFString = "B";
|
||||
else if (red == 12) rFString = "C";
|
||||
else if (red == 13) rFString = "D";
|
||||
else if (red == 14) rFString = "E";
|
||||
else if (red == 15) rFString = "F";
|
||||
else rFString = String.valueOf(red);
|
||||
|
||||
if (rred == 10) rSString = "A";
|
||||
else if (rred == 11) rSString = "B";
|
||||
else if (rred == 12) rSString = "C";
|
||||
else if (rred == 13) rSString = "D";
|
||||
else if (rred == 14) rSString = "E";
|
||||
else if (rred == 15) rSString = "F";
|
||||
else rSString = String.valueOf(rred);
|
||||
|
||||
rFString = rFString + rSString;
|
||||
|
||||
green = g / 16;
|
||||
rgreen = g % 16;
|
||||
|
||||
if (green == 10) gFString = "A";
|
||||
else if (green == 11) gFString = "B";
|
||||
else if (green == 12) gFString = "C";
|
||||
else if (green == 13) gFString = "D";
|
||||
else if (green == 14) gFString = "E";
|
||||
else if (green == 15) gFString = "F";
|
||||
else gFString = String.valueOf(green);
|
||||
|
||||
if (rgreen == 10) gSString = "A";
|
||||
else if (rgreen == 11) gSString = "B";
|
||||
else if (rgreen == 12) gSString = "C";
|
||||
else if (rgreen == 13) gSString = "D";
|
||||
else if (rgreen == 14) gSString = "E";
|
||||
else if (rgreen == 15) gSString = "F";
|
||||
else gSString = String.valueOf(rgreen);
|
||||
|
||||
gFString = gFString + gSString;
|
||||
|
||||
blue = b / 16;
|
||||
rblue = b % 16;
|
||||
|
||||
if (blue == 10) bFString = "A";
|
||||
else if (blue == 11) bFString = "B";
|
||||
else if (blue == 12) bFString = "C";
|
||||
else if (blue == 13) bFString = "D";
|
||||
else if (blue == 14) bFString = "E";
|
||||
else if (blue == 15) bFString = "F";
|
||||
else bFString = String.valueOf(blue);
|
||||
|
||||
if (rblue == 10) bSString = "A";
|
||||
else if (rblue == 11) bSString = "B";
|
||||
else if (rblue == 12) bSString = "C";
|
||||
else if (rblue == 13) bSString = "D";
|
||||
else if (rblue == 14) bSString = "E";
|
||||
else if (rblue == 15) bSString = "F";
|
||||
else bSString = String.valueOf(rblue);
|
||||
bFString = bFString + bSString;
|
||||
result = "#" + rFString + gFString + bFString;
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
public static int[] getRGB(String rgb) {
|
||||
int[] ret = new int[3];
|
||||
for (int i = 0; i < 3; i++) {
|
||||
ret[i] = Integer.parseInt(rgb.substring(i * 2, i * 2 + 2), 16);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static String[] roman_thousands = {"", "M", "MM", "MMM"};
|
||||
private static String[] roman_hundreds = {"", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"};
|
||||
private static String[] roman_tens = {"", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"};
|
||||
private static String[] roman_ones = {"", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"};
|
||||
|
||||
public static String intToRoman(int num) {
|
||||
StringBuffer roman = new StringBuffer();
|
||||
roman.append(roman_thousands[num / 1000]);
|
||||
roman.append(roman_hundreds[num % 1000 / 100]);
|
||||
roman.append(roman_tens[num % 100 / 10]);
|
||||
roman.append(roman_ones[num % 10]);
|
||||
return roman.toString();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
package com.io.yutian.aulib.util;
|
||||
|
||||
import net.md_5.bungee.api.chat.ClickEvent;
|
||||
import net.md_5.bungee.api.chat.HoverEvent;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
|
||||
public class TextComponentBuilder {
|
||||
|
||||
private TextComponent textComponent;
|
||||
|
||||
public TextComponentBuilder() {
|
||||
this.textComponent = new TextComponent();
|
||||
}
|
||||
|
||||
public TextComponentBuilder addText(String text) {
|
||||
textComponent.addExtra(text);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TextComponentBuilder addText(String text, ClickEvent clickEvent) {
|
||||
TextComponent component = new TextComponent(text);
|
||||
component.setClickEvent(clickEvent);
|
||||
this.textComponent.addExtra(component);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TextComponentBuilder addText(String text, ClickEvent clickEvent, HoverEvent hoverEvent) {
|
||||
TextComponent component = new TextComponent(text);
|
||||
component.setClickEvent(clickEvent);
|
||||
component.setHoverEvent(hoverEvent);
|
||||
this.textComponent.addExtra(component);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TextComponentBuilder addText(String text, HoverEvent hoverEvent) {
|
||||
TextComponent component = new TextComponent(text);
|
||||
component.setHoverEvent(hoverEvent);
|
||||
this.textComponent.addExtra(component);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TextComponent build() {
|
||||
return textComponent;
|
||||
}
|
||||
}
|
97
src/main/java/com/io/yutian/aulib/util/TimeUtil.java
Normal file
97
src/main/java/com/io/yutian/aulib/util/TimeUtil.java
Normal file
|
@ -0,0 +1,97 @@
|
|||
package com.io.yutian.aulib.util;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
|
||||
public class TimeUtil {
|
||||
|
||||
private static final int HOUR_SECOND = 60 * 60;
|
||||
private static final int MINUTE_SECOND = 60;
|
||||
|
||||
public static boolean inOreDay(long time1, long time2) {
|
||||
Date date = new Date(time1);
|
||||
Date date2 = new Date(time2);
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
Calendar calendar2 = Calendar.getInstance();
|
||||
calendar.setTime(date);
|
||||
int y1 = calendar.get(Calendar.YEAR);
|
||||
int d1 = calendar.get(Calendar.DAY_OF_YEAR);
|
||||
calendar2.setTime(date2);
|
||||
|
||||
int y2 = calendar2.get(Calendar.YEAR);
|
||||
int d2 = calendar2.get(Calendar.DAY_OF_YEAR);
|
||||
return y1 == y2 && d1 == d2;
|
||||
}
|
||||
|
||||
public static boolean inOreWeek(long time1, long time2) {
|
||||
Date date = new Date(time1);
|
||||
Date date2 = new Date(time2);
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
Calendar calendar2 = Calendar.getInstance();
|
||||
calendar.setTime(date);
|
||||
int y1 = calendar.get(Calendar.YEAR);
|
||||
int d1 = calendar.get(Calendar.WEEK_OF_YEAR);
|
||||
calendar2.setTime(date2);
|
||||
int y2 = calendar2.get(Calendar.YEAR);
|
||||
int d2 = calendar2.get(Calendar.WEEK_OF_YEAR);
|
||||
return y1 == y2 && d1 == d2;
|
||||
}
|
||||
|
||||
public static boolean inOreMonth(long time1, long time2) {
|
||||
Date date = new Date(time1);
|
||||
Date date2 = new Date(time2);
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
Calendar calendar2 = Calendar.getInstance();
|
||||
calendar.setTime(date);
|
||||
int y1 = calendar.get(Calendar.YEAR);
|
||||
int d1 = calendar.get(Calendar.MONTH);
|
||||
calendar2.setTime(date2);
|
||||
int y2 = calendar2.get(Calendar.YEAR);
|
||||
int d2 = calendar2.get(Calendar.MONTH);
|
||||
return y1 == y2 && d1 == d2;
|
||||
}
|
||||
|
||||
public static String timeToString(long time) {
|
||||
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy/MM/dd");
|
||||
return simpleDateFormat.format(new Date(time));
|
||||
}
|
||||
|
||||
public static String getTimeStringBySecondFormat(long second) {
|
||||
if (second <= 0) {
|
||||
return "0小时0分钟0秒";
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
long hours = second / HOUR_SECOND;
|
||||
if (hours > 0) {
|
||||
second -= hours * HOUR_SECOND;
|
||||
}
|
||||
long minutes = second / MINUTE_SECOND;
|
||||
if (minutes > 0) {
|
||||
second -= minutes * MINUTE_SECOND;
|
||||
}
|
||||
String hoursString = String.valueOf(hours);
|
||||
String minutesString = (minutes >= 10 ? (minutes + "") : ("0" + minutes));
|
||||
String secondString = (second >= 10 ? (second + "") : ("0" + second));
|
||||
return hoursString+"小时"+minutesString+"分钟"+secondString+"秒";
|
||||
}
|
||||
|
||||
public static String getTimeStringBySecond(long second) {
|
||||
if (second <= 0) {
|
||||
return "00:00:00";
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
long hours = second / HOUR_SECOND;
|
||||
if (hours > 0) {
|
||||
second -= hours * HOUR_SECOND;
|
||||
}
|
||||
long minutes = second / MINUTE_SECOND;
|
||||
if (minutes > 0) {
|
||||
second -= minutes * MINUTE_SECOND;
|
||||
}
|
||||
return (hours >= 10 ? (hours + "")
|
||||
: ("0" + hours) + ":" + (minutes >= 10 ? (minutes + "") : ("0" + minutes)) + ":"
|
||||
+ (second >= 10 ? (second + "") : ("0" + second)));
|
||||
}
|
||||
|
||||
}
|
1517
src/main/java/org/json/JSONArray.java
Normal file
1517
src/main/java/org/json/JSONArray.java
Normal file
File diff suppressed because it is too large
Load Diff
45
src/main/java/org/json/JSONException.java
Normal file
45
src/main/java/org/json/JSONException.java
Normal file
|
@ -0,0 +1,45 @@
|
|||
package org.json;
|
||||
|
||||
/**
|
||||
* The JSONException is thrown by the JSON.org classes when things are amiss.
|
||||
*
|
||||
* @author JSON.org
|
||||
* @version 2015-12-09
|
||||
*/
|
||||
public class JSONException extends RuntimeException {
|
||||
/** Serialization ID */
|
||||
private static final long serialVersionUID = 0;
|
||||
|
||||
/**
|
||||
* Constructs a JSONException with an explanatory message.
|
||||
*
|
||||
* @param message
|
||||
* Detail about the reason for the exception.
|
||||
*/
|
||||
public JSONException(final String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a JSONException with an explanatory message and cause.
|
||||
*
|
||||
* @param message
|
||||
* Detail about the reason for the exception.
|
||||
* @param cause
|
||||
* The cause.
|
||||
*/
|
||||
public JSONException(final String message, final Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new JSONException with the specified cause.
|
||||
*
|
||||
* @param cause
|
||||
* The cause.
|
||||
*/
|
||||
public JSONException(final Throwable cause) {
|
||||
super(cause.getMessage(), cause);
|
||||
}
|
||||
|
||||
}
|
2647
src/main/java/org/json/JSONObject.java
Normal file
2647
src/main/java/org/json/JSONObject.java
Normal file
File diff suppressed because it is too large
Load Diff
293
src/main/java/org/json/JSONPointer.java
Normal file
293
src/main/java/org/json/JSONPointer.java
Normal file
|
@ -0,0 +1,293 @@
|
|||
package org.json;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLDecoder;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static java.lang.String.format;
|
||||
|
||||
/*
|
||||
Copyright (c) 2002 JSON.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
The Software shall be used for Good, not Evil.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* A JSON Pointer is a simple query language defined for JSON documents by
|
||||
* <a href="https://tools.ietf.org/html/rfc6901">RFC 6901</a>.
|
||||
*
|
||||
* In a nutshell, JSONPointer allows the user to navigate into a JSON document
|
||||
* using strings, and retrieve targeted objects, like a simple form of XPATH.
|
||||
* Path segments are separated by the '/' char, which signifies the root of
|
||||
* the document when it appears as the first char of the string. Array
|
||||
* elements are navigated using ordinals, counting from 0. JSONPointer strings
|
||||
* may be extended to any arbitrary number of segments. If the navigation
|
||||
* is successful, the matched item is returned. A matched item may be a
|
||||
* JSONObject, a JSONArray, or a JSON value. If the JSONPointer string building
|
||||
* fails, an appropriate exception is thrown. If the navigation fails to find
|
||||
* a match, a JSONPointerException is thrown.
|
||||
*
|
||||
* @author JSON.org
|
||||
* @version 2016-05-14
|
||||
*/
|
||||
public class JSONPointer {
|
||||
|
||||
// used for URL encoding and decoding
|
||||
private static final String ENCODING = "utf-8";
|
||||
|
||||
/**
|
||||
* This class allows the user to build a JSONPointer in steps, using
|
||||
* exactly one segment in each step.
|
||||
*/
|
||||
public static class Builder {
|
||||
|
||||
// Segments for the eventual JSONPointer string
|
||||
private final List<String> refTokens = new ArrayList<String>();
|
||||
|
||||
/**
|
||||
* Creates a {@code JSONPointer} instance using the tokens previously set using the
|
||||
* {@link #append(String)} method calls.
|
||||
*/
|
||||
public JSONPointer build() {
|
||||
return new JSONPointer(this.refTokens);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an arbitrary token to the list of reference tokens. It can be any non-null value.
|
||||
*
|
||||
* Unlike in the case of JSON string or URI fragment representation of JSON pointers, the
|
||||
* argument of this method MUST NOT be escaped. If you want to query the property called
|
||||
* {@code "a~b"} then you should simply pass the {@code "a~b"} string as-is, there is no
|
||||
* need to escape it as {@code "a~0b"}.
|
||||
*
|
||||
* @param token the new token to be appended to the list
|
||||
* @return {@code this}
|
||||
* @throws NullPointerException if {@code token} is null
|
||||
*/
|
||||
public Builder append(String token) {
|
||||
if (token == null) {
|
||||
throw new NullPointerException("token cannot be null");
|
||||
}
|
||||
this.refTokens.add(token);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an integer to the reference token list. Although not necessarily, mostly this token will
|
||||
* denote an array index.
|
||||
*
|
||||
* @param arrayIndex the array index to be added to the token list
|
||||
* @return {@code this}
|
||||
*/
|
||||
public Builder append(int arrayIndex) {
|
||||
this.refTokens.add(String.valueOf(arrayIndex));
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Static factory method for {@link Builder}. Example usage:
|
||||
*
|
||||
* <pre><code>
|
||||
* JSONPointer pointer = JSONPointer.builder()
|
||||
* .append("obj")
|
||||
* .append("other~key").append("another/key")
|
||||
* .append("\"")
|
||||
* .append(0)
|
||||
* .build();
|
||||
* </code></pre>
|
||||
*
|
||||
* @return a builder instance which can be used to construct a {@code JSONPointer} instance by chained
|
||||
* {@link Builder#append(String)} calls.
|
||||
*/
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
// Segments for the JSONPointer string
|
||||
private final List<String> refTokens;
|
||||
|
||||
/**
|
||||
* Pre-parses and initializes a new {@code JSONPointer} instance. If you want to
|
||||
* evaluate the same JSON Pointer on different JSON documents then it is recommended
|
||||
* to keep the {@code JSONPointer} instances due to performance considerations.
|
||||
*
|
||||
* @param pointer the JSON String or URI Fragment representation of the JSON pointer.
|
||||
* @throws IllegalArgumentException if {@code pointer} is not a valid JSON pointer
|
||||
*/
|
||||
public JSONPointer(final String pointer) {
|
||||
if (pointer == null) {
|
||||
throw new NullPointerException("pointer cannot be null");
|
||||
}
|
||||
if (pointer.isEmpty() || pointer.equals("#")) {
|
||||
this.refTokens = Collections.emptyList();
|
||||
return;
|
||||
}
|
||||
String refs;
|
||||
if (pointer.startsWith("#/")) {
|
||||
refs = pointer.substring(2);
|
||||
try {
|
||||
refs = URLDecoder.decode(refs, ENCODING);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
} else if (pointer.startsWith("/")) {
|
||||
refs = pointer.substring(1);
|
||||
} else {
|
||||
throw new IllegalArgumentException("a JSON pointer should start with '/' or '#/'");
|
||||
}
|
||||
this.refTokens = new ArrayList<String>();
|
||||
int slashIdx = -1;
|
||||
int prevSlashIdx = 0;
|
||||
do {
|
||||
prevSlashIdx = slashIdx + 1;
|
||||
slashIdx = refs.indexOf('/', prevSlashIdx);
|
||||
if(prevSlashIdx == slashIdx || prevSlashIdx == refs.length()) {
|
||||
// found 2 slashes in a row ( obj//next )
|
||||
// or single slash at the end of a string ( obj/test/ )
|
||||
this.refTokens.add("");
|
||||
} else if (slashIdx >= 0) {
|
||||
final String token = refs.substring(prevSlashIdx, slashIdx);
|
||||
this.refTokens.add(unescape(token));
|
||||
} else {
|
||||
// last item after separator, or no separator at all.
|
||||
final String token = refs.substring(prevSlashIdx);
|
||||
this.refTokens.add(unescape(token));
|
||||
}
|
||||
} while (slashIdx >= 0);
|
||||
// using split does not take into account consecutive separators or "ending nulls"
|
||||
//for (String token : refs.split("/")) {
|
||||
// this.refTokens.add(unescape(token));
|
||||
//}
|
||||
}
|
||||
|
||||
public JSONPointer(List<String> refTokens) {
|
||||
this.refTokens = new ArrayList<String>(refTokens);
|
||||
}
|
||||
|
||||
private static String unescape(String token) {
|
||||
return token.replace("~1", "/").replace("~0", "~")
|
||||
.replace("\\\"", "\"")
|
||||
.replace("\\\\", "\\");
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluates this JSON Pointer on the given {@code document}. The {@code document}
|
||||
* is usually a {@link JSONObject} or a {@link JSONArray} instance, but the empty
|
||||
* JSON Pointer ({@code ""}) can be evaluated on any JSON values and in such case the
|
||||
* returned value will be {@code document} itself.
|
||||
*
|
||||
* @param document the JSON document which should be the subject of querying.
|
||||
* @return the result of the evaluation
|
||||
* @throws JSONPointerException if an error occurs during evaluation
|
||||
*/
|
||||
public Object queryFrom(Object document) throws JSONPointerException {
|
||||
if (this.refTokens.isEmpty()) {
|
||||
return document;
|
||||
}
|
||||
Object current = document;
|
||||
for (String token : this.refTokens) {
|
||||
if (current instanceof JSONObject) {
|
||||
current = ((JSONObject) current).opt(unescape(token));
|
||||
} else if (current instanceof JSONArray) {
|
||||
current = readByIndexToken(current, token);
|
||||
} else {
|
||||
throw new JSONPointerException(format(
|
||||
"value [%s] is not an array or object therefore its key %s cannot be resolved", current,
|
||||
token));
|
||||
}
|
||||
}
|
||||
return current;
|
||||
}
|
||||
|
||||
/**
|
||||
* Matches a JSONArray element by ordinal position
|
||||
* @param current the JSONArray to be evaluated
|
||||
* @param indexToken the array index in string form
|
||||
* @return the matched object. If no matching item is found a
|
||||
* @throws JSONPointerException is thrown if the index is out of bounds
|
||||
*/
|
||||
private static Object readByIndexToken(Object current, String indexToken) throws JSONPointerException {
|
||||
try {
|
||||
int index = Integer.parseInt(indexToken);
|
||||
JSONArray currentArr = (JSONArray) current;
|
||||
if (index >= currentArr.length()) {
|
||||
throw new JSONPointerException(format("index %s is out of bounds - the array has %d elements", indexToken,
|
||||
Integer.valueOf(currentArr.length())));
|
||||
}
|
||||
try {
|
||||
return currentArr.get(index);
|
||||
} catch (JSONException e) {
|
||||
throw new JSONPointerException("Error reading value at index position " + index, e);
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
throw new JSONPointerException(format("%s is not an array index", indexToken), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representing the JSONPointer path value using string
|
||||
* representation
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder rval = new StringBuilder("");
|
||||
for (String token: this.refTokens) {
|
||||
rval.append('/').append(escape(token));
|
||||
}
|
||||
return rval.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Escapes path segment values to an unambiguous form.
|
||||
* The escape char to be inserted is '~'. The chars to be escaped
|
||||
* are ~, which maps to ~0, and /, which maps to ~1. Backslashes
|
||||
* and double quote chars are also escaped.
|
||||
* @param token the JSONPointer segment value to be escaped
|
||||
* @return the escaped value for the token
|
||||
*/
|
||||
private static String escape(String token) {
|
||||
return token.replace("~", "~0")
|
||||
.replace("/", "~1")
|
||||
.replace("\\", "\\\\")
|
||||
.replace("\"", "\\\"");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representing the JSONPointer path value using URI
|
||||
* fragment identifier representation
|
||||
*/
|
||||
public String toURIFragment() {
|
||||
try {
|
||||
StringBuilder rval = new StringBuilder("#");
|
||||
for (String token : this.refTokens) {
|
||||
rval.append('/').append(URLEncoder.encode(token, ENCODING));
|
||||
}
|
||||
return rval.toString();
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
45
src/main/java/org/json/JSONPointerException.java
Normal file
45
src/main/java/org/json/JSONPointerException.java
Normal file
|
@ -0,0 +1,45 @@
|
|||
package org.json;
|
||||
|
||||
/*
|
||||
Copyright (c) 2002 JSON.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
The Software shall be used for Good, not Evil.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The JSONPointerException is thrown by {@link JSONPointer} if an error occurs
|
||||
* during evaluating a pointer.
|
||||
*
|
||||
* @author JSON.org
|
||||
* @version 2016-05-13
|
||||
*/
|
||||
public class JSONPointerException extends JSONException {
|
||||
private static final long serialVersionUID = 8872944667561856751L;
|
||||
|
||||
public JSONPointerException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public JSONPointerException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
}
|
43
src/main/java/org/json/JSONPropertyIgnore.java
Normal file
43
src/main/java/org/json/JSONPropertyIgnore.java
Normal file
|
@ -0,0 +1,43 @@
|
|||
package org.json;
|
||||
|
||||
/*
|
||||
Copyright (c) 2018 JSON.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
The Software shall be used for Good, not Evil.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.METHOD;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
@Documented
|
||||
@Retention(RUNTIME)
|
||||
@Target({METHOD})
|
||||
/**
|
||||
* Use this annotation on a getter method to override the Bean name
|
||||
* parser for Bean -> JSONObject mapping. If this annotation is
|
||||
* present at any level in the class hierarchy, then the method will
|
||||
* not be serialized from the bean into the JSONObject.
|
||||
*/
|
||||
public @interface JSONPropertyIgnore { }
|
47
src/main/java/org/json/JSONPropertyName.java
Normal file
47
src/main/java/org/json/JSONPropertyName.java
Normal file
|
@ -0,0 +1,47 @@
|
|||
package org.json;
|
||||
|
||||
/*
|
||||
Copyright (c) 2018 JSON.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
The Software shall be used for Good, not Evil.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.METHOD;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
@Documented
|
||||
@Retention(RUNTIME)
|
||||
@Target({METHOD})
|
||||
/**
|
||||
* Use this annotation on a getter method to override the Bean name
|
||||
* parser for Bean -> JSONObject mapping. A value set to empty string <code>""</code>
|
||||
* will have the Bean parser fall back to the default field name processing.
|
||||
*/
|
||||
public @interface JSONPropertyName {
|
||||
/**
|
||||
* @return The name of the property as to be used in the JSON Object.
|
||||
*/
|
||||
String value();
|
||||
}
|
18
src/main/java/org/json/JSONString.java
Normal file
18
src/main/java/org/json/JSONString.java
Normal file
|
@ -0,0 +1,18 @@
|
|||
package org.json;
|
||||
/**
|
||||
* The <code>JSONString</code> interface allows a <code>toJSONString()</code>
|
||||
* method so that a class can change the behavior of
|
||||
* <code>JSONObject.toString()</code>, <code>JSONArray.toString()</code>,
|
||||
* and <code>JSONWriter.value(</code>Object<code>)</code>. The
|
||||
* <code>toJSONString</code> method will be used instead of the default behavior
|
||||
* of using the Object's <code>toString()</code> method and quoting the result.
|
||||
*/
|
||||
public interface JSONString {
|
||||
/**
|
||||
* The <code>toJSONString</code> method allows a class to produce its own JSON
|
||||
* serialization.
|
||||
*
|
||||
* @return A strictly syntactically correct JSON text.
|
||||
*/
|
||||
public String toJSONString();
|
||||
}
|
79
src/main/java/org/json/JSONStringer.java
Normal file
79
src/main/java/org/json/JSONStringer.java
Normal file
|
@ -0,0 +1,79 @@
|
|||
package org.json;
|
||||
|
||||
/*
|
||||
Copyright (c) 2006 JSON.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
The Software shall be used for Good, not Evil.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
import java.io.StringWriter;
|
||||
|
||||
/**
|
||||
* JSONStringer provides a quick and convenient way of producing JSON text.
|
||||
* The texts produced strictly conform to JSON syntax rules. No whitespace is
|
||||
* added, so the results are ready for transmission or storage. Each instance of
|
||||
* JSONStringer can produce one JSON text.
|
||||
* <p>
|
||||
* A JSONStringer instance provides a <code>value</code> method for appending
|
||||
* values to the
|
||||
* text, and a <code>key</code>
|
||||
* method for adding keys before values in objects. There are <code>array</code>
|
||||
* and <code>endArray</code> methods that make and bound array values, and
|
||||
* <code>object</code> and <code>endObject</code> methods which make and bound
|
||||
* object values. All of these methods return the JSONWriter instance,
|
||||
* permitting cascade style. For example, <pre>
|
||||
* myString = new JSONStringer()
|
||||
* .object()
|
||||
* .key("JSON")
|
||||
* .value("Hello, World!")
|
||||
* .endObject()
|
||||
* .toString();</pre> which produces the string <pre>
|
||||
* {"JSON":"Hello, World!"}</pre>
|
||||
* <p>
|
||||
* The first method called must be <code>array</code> or <code>object</code>.
|
||||
* There are no methods for adding commas or colons. JSONStringer adds them for
|
||||
* you. Objects and arrays can be nested up to 20 levels deep.
|
||||
* <p>
|
||||
* This can sometimes be easier than using a JSONObject to build a string.
|
||||
* @author JSON.org
|
||||
* @version 2015-12-09
|
||||
*/
|
||||
public class JSONStringer extends JSONWriter {
|
||||
/**
|
||||
* Make a fresh JSONStringer. It can be used to build one JSON text.
|
||||
*/
|
||||
public JSONStringer() {
|
||||
super(new StringWriter());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the JSON text. This method is used to obtain the product of the
|
||||
* JSONStringer instance. It will return <code>null</code> if there was a
|
||||
* problem in the construction of the JSON text (such as the calls to
|
||||
* <code>array</code> were not properly balanced with calls to
|
||||
* <code>endArray</code>).
|
||||
* @return The JSON text.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.mode == 'd' ? this.writer.toString() : null;
|
||||
}
|
||||
}
|
526
src/main/java/org/json/JSONTokener.java
Normal file
526
src/main/java/org/json/JSONTokener.java
Normal file
|
@ -0,0 +1,526 @@
|
|||
package org.json;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
/*
|
||||
Copyright (c) 2002 JSON.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
The Software shall be used for Good, not Evil.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* A JSONTokener takes a source string and extracts characters and tokens from
|
||||
* it. It is used by the JSONObject and JSONArray constructors to parse
|
||||
* JSON source strings.
|
||||
* @author JSON.org
|
||||
* @version 2014-05-03
|
||||
*/
|
||||
public class JSONTokener {
|
||||
/** current read character position on the current line. */
|
||||
private long character;
|
||||
/** flag to indicate if the end of the input has been found. */
|
||||
private boolean eof;
|
||||
/** current read index of the input. */
|
||||
private long index;
|
||||
/** current line of the input. */
|
||||
private long line;
|
||||
/** previous character read from the input. */
|
||||
private char previous;
|
||||
/** Reader for the input. */
|
||||
private final Reader reader;
|
||||
/** flag to indicate that a previous character was requested. */
|
||||
private boolean usePrevious;
|
||||
/** the number of characters read in the previous line. */
|
||||
private long characterPreviousLine;
|
||||
|
||||
|
||||
/**
|
||||
* Construct a JSONTokener from a Reader. The caller must close the Reader.
|
||||
*
|
||||
* @param reader A reader.
|
||||
*/
|
||||
public JSONTokener(Reader reader) {
|
||||
this.reader = reader.markSupported()
|
||||
? reader
|
||||
: new BufferedReader(reader);
|
||||
this.eof = false;
|
||||
this.usePrevious = false;
|
||||
this.previous = 0;
|
||||
this.index = 0;
|
||||
this.character = 1;
|
||||
this.characterPreviousLine = 0;
|
||||
this.line = 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Construct a JSONTokener from an InputStream. The caller must close the input stream.
|
||||
* @param inputStream The source.
|
||||
*/
|
||||
public JSONTokener(InputStream inputStream) {
|
||||
this(new InputStreamReader(inputStream));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Construct a JSONTokener from a string.
|
||||
*
|
||||
* @param s A source string.
|
||||
*/
|
||||
public JSONTokener(String s) {
|
||||
this(new StringReader(s));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Back up one character. This provides a sort of lookahead capability,
|
||||
* so that you can test for a digit or letter before attempting to parse
|
||||
* the next number or identifier.
|
||||
* @throws JSONException Thrown if trying to step back more than 1 step
|
||||
* or if already at the start of the string
|
||||
*/
|
||||
public void back() throws JSONException {
|
||||
if (this.usePrevious || this.index <= 0) {
|
||||
throw new JSONException("Stepping back two steps is not supported");
|
||||
}
|
||||
this.decrementIndexes();
|
||||
this.usePrevious = true;
|
||||
this.eof = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrements the indexes for the {@link #back()} method based on the previous character read.
|
||||
*/
|
||||
private void decrementIndexes() {
|
||||
this.index--;
|
||||
if(this.previous=='\r' || this.previous == '\n') {
|
||||
this.line--;
|
||||
this.character=this.characterPreviousLine ;
|
||||
} else if(this.character > 0){
|
||||
this.character--;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the hex value of a character (base16).
|
||||
* @param c A character between '0' and '9' or between 'A' and 'F' or
|
||||
* between 'a' and 'f'.
|
||||
* @return An int between 0 and 15, or -1 if c was not a hex digit.
|
||||
*/
|
||||
public static int dehexchar(char c) {
|
||||
if (c >= '0' && c <= '9') {
|
||||
return c - '0';
|
||||
}
|
||||
if (c >= 'A' && c <= 'F') {
|
||||
return c - ('A' - 10);
|
||||
}
|
||||
if (c >= 'a' && c <= 'f') {
|
||||
return c - ('a' - 10);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the end of the input has been reached.
|
||||
*
|
||||
* @return true if at the end of the file and we didn't step back
|
||||
*/
|
||||
public boolean end() {
|
||||
return this.eof && !this.usePrevious;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determine if the source string still contains characters that next()
|
||||
* can consume.
|
||||
* @return true if not yet at the end of the source.
|
||||
* @throws JSONException thrown if there is an error stepping forward
|
||||
* or backward while checking for more data.
|
||||
*/
|
||||
public boolean more() throws JSONException {
|
||||
if(this.usePrevious) {
|
||||
return true;
|
||||
}
|
||||
try {
|
||||
this.reader.mark(1);
|
||||
} catch (IOException e) {
|
||||
throw new JSONException("Unable to preserve stream position", e);
|
||||
}
|
||||
try {
|
||||
// -1 is EOF, but next() can not consume the null character '\0'
|
||||
if(this.reader.read() <= 0) {
|
||||
this.eof = true;
|
||||
return false;
|
||||
}
|
||||
this.reader.reset();
|
||||
} catch (IOException e) {
|
||||
throw new JSONException("Unable to read the next character from the stream", e);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the next character in the source string.
|
||||
*
|
||||
* @return The next character, or 0 if past the end of the source string.
|
||||
* @throws JSONException Thrown if there is an error reading the source string.
|
||||
*/
|
||||
public char next() throws JSONException {
|
||||
int c;
|
||||
if (this.usePrevious) {
|
||||
this.usePrevious = false;
|
||||
c = this.previous;
|
||||
} else {
|
||||
try {
|
||||
c = this.reader.read();
|
||||
} catch (IOException exception) {
|
||||
throw new JSONException(exception);
|
||||
}
|
||||
}
|
||||
if (c <= 0) { // End of stream
|
||||
this.eof = true;
|
||||
return 0;
|
||||
}
|
||||
this.incrementIndexes(c);
|
||||
this.previous = (char) c;
|
||||
return this.previous;
|
||||
}
|
||||
|
||||
/**
|
||||
* Increments the internal indexes according to the previous character
|
||||
* read and the character passed as the current character.
|
||||
* @param c the current character read.
|
||||
*/
|
||||
private void incrementIndexes(int c) {
|
||||
if(c > 0) {
|
||||
this.index++;
|
||||
if(c=='\r') {
|
||||
this.line++;
|
||||
this.characterPreviousLine = this.character;
|
||||
this.character=0;
|
||||
}else if (c=='\n') {
|
||||
if(this.previous != '\r') {
|
||||
this.line++;
|
||||
this.characterPreviousLine = this.character;
|
||||
}
|
||||
this.character=0;
|
||||
} else {
|
||||
this.character++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Consume the next character, and check that it matches a specified
|
||||
* character.
|
||||
* @param c The character to match.
|
||||
* @return The character.
|
||||
* @throws JSONException if the character does not match.
|
||||
*/
|
||||
public char next(char c) throws JSONException {
|
||||
char n = this.next();
|
||||
if (n != c) {
|
||||
if(n > 0) {
|
||||
throw this.syntaxError("Expected '" + c + "' and instead saw '" +
|
||||
n + "'");
|
||||
}
|
||||
throw this.syntaxError("Expected '" + c + "' and instead saw ''");
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the next n characters.
|
||||
*
|
||||
* @param n The number of characters to take.
|
||||
* @return A string of n characters.
|
||||
* @throws JSONException
|
||||
* Substring bounds error if there are not
|
||||
* n characters remaining in the source string.
|
||||
*/
|
||||
public String next(int n) throws JSONException {
|
||||
if (n == 0) {
|
||||
return "";
|
||||
}
|
||||
|
||||
char[] chars = new char[n];
|
||||
int pos = 0;
|
||||
|
||||
while (pos < n) {
|
||||
chars[pos] = this.next();
|
||||
if (this.end()) {
|
||||
throw this.syntaxError("Substring bounds error");
|
||||
}
|
||||
pos += 1;
|
||||
}
|
||||
return new String(chars);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the next char in the string, skipping whitespace.
|
||||
* @throws JSONException Thrown if there is an error reading the source string.
|
||||
* @return A character, or 0 if there are no more characters.
|
||||
*/
|
||||
public char nextClean() throws JSONException {
|
||||
for (;;) {
|
||||
char c = this.next();
|
||||
if (c == 0 || c > ' ') {
|
||||
return c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the characters up to the next close quote character.
|
||||
* Backslash processing is done. The formal JSON format does not
|
||||
* allow strings in single quotes, but an implementation is allowed to
|
||||
* accept them.
|
||||
* @param quote The quoting character, either
|
||||
* <code>"</code> <small>(double quote)</small> or
|
||||
* <code>'</code> <small>(single quote)</small>.
|
||||
* @return A String.
|
||||
* @throws JSONException Unterminated string.
|
||||
*/
|
||||
public String nextString(char quote) throws JSONException {
|
||||
char c;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (;;) {
|
||||
c = this.next();
|
||||
switch (c) {
|
||||
case 0:
|
||||
case '\n':
|
||||
case '\r':
|
||||
throw this.syntaxError("Unterminated string");
|
||||
case '\\':
|
||||
c = this.next();
|
||||
switch (c) {
|
||||
case 'b':
|
||||
sb.append('\b');
|
||||
break;
|
||||
case 't':
|
||||
sb.append('\t');
|
||||
break;
|
||||
case 'n':
|
||||
sb.append('\n');
|
||||
break;
|
||||
case 'f':
|
||||
sb.append('\f');
|
||||
break;
|
||||
case 'r':
|
||||
sb.append('\r');
|
||||
break;
|
||||
case 'u':
|
||||
try {
|
||||
sb.append((char)Integer.parseInt(this.next(4), 16));
|
||||
} catch (NumberFormatException e) {
|
||||
throw this.syntaxError("Illegal escape.", e);
|
||||
}
|
||||
break;
|
||||
case '"':
|
||||
case '\'':
|
||||
case '\\':
|
||||
case '/':
|
||||
sb.append(c);
|
||||
break;
|
||||
default:
|
||||
throw this.syntaxError("Illegal escape.");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (c == quote) {
|
||||
return sb.toString();
|
||||
}
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the text up but not including the specified character or the
|
||||
* end of line, whichever comes first.
|
||||
* @param delimiter A delimiter character.
|
||||
* @return A string.
|
||||
* @throws JSONException Thrown if there is an error while searching
|
||||
* for the delimiter
|
||||
*/
|
||||
public String nextTo(char delimiter) throws JSONException {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (;;) {
|
||||
char c = this.next();
|
||||
if (c == delimiter || c == 0 || c == '\n' || c == '\r') {
|
||||
if (c != 0) {
|
||||
this.back();
|
||||
}
|
||||
return sb.toString().trim();
|
||||
}
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the text up but not including one of the specified delimiter
|
||||
* characters or the end of line, whichever comes first.
|
||||
* @param delimiters A set of delimiter characters.
|
||||
* @return A string, trimmed.
|
||||
* @throws JSONException Thrown if there is an error while searching
|
||||
* for the delimiter
|
||||
*/
|
||||
public String nextTo(String delimiters) throws JSONException {
|
||||
char c;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (;;) {
|
||||
c = this.next();
|
||||
if (delimiters.indexOf(c) >= 0 || c == 0 ||
|
||||
c == '\n' || c == '\r') {
|
||||
if (c != 0) {
|
||||
this.back();
|
||||
}
|
||||
return sb.toString().trim();
|
||||
}
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the next value. The value can be a Boolean, Double, Integer,
|
||||
* JSONArray, JSONObject, Long, or String, or the JSONObject.NULL object.
|
||||
* @throws JSONException If syntax error.
|
||||
*
|
||||
* @return An object.
|
||||
*/
|
||||
public Object nextValue() throws JSONException {
|
||||
char c = this.nextClean();
|
||||
String string;
|
||||
|
||||
switch (c) {
|
||||
case '"':
|
||||
case '\'':
|
||||
return this.nextString(c);
|
||||
case '{':
|
||||
this.back();
|
||||
return new JSONObject(this);
|
||||
case '[':
|
||||
this.back();
|
||||
return new JSONArray(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle unquoted text. This could be the values true, false, or
|
||||
* null, or it can be a number. An implementation (such as this one)
|
||||
* is allowed to also accept non-standard forms.
|
||||
*
|
||||
* Accumulate characters until we reach the end of the text or a
|
||||
* formatting character.
|
||||
*/
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
while (c >= ' ' && ",:]}/\\\"[{;=#".indexOf(c) < 0) {
|
||||
sb.append(c);
|
||||
c = this.next();
|
||||
}
|
||||
if (!this.eof) {
|
||||
this.back();
|
||||
}
|
||||
|
||||
string = sb.toString().trim();
|
||||
if ("".equals(string)) {
|
||||
throw this.syntaxError("Missing value");
|
||||
}
|
||||
return JSONObject.stringToValue(string);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Skip characters until the next character is the requested character.
|
||||
* If the requested character is not found, no characters are skipped.
|
||||
* @param to A character to skip to.
|
||||
* @return The requested character, or zero if the requested character
|
||||
* is not found.
|
||||
* @throws JSONException Thrown if there is an error while searching
|
||||
* for the to character
|
||||
*/
|
||||
public char skipTo(char to) throws JSONException {
|
||||
char c;
|
||||
try {
|
||||
long startIndex = this.index;
|
||||
long startCharacter = this.character;
|
||||
long startLine = this.line;
|
||||
this.reader.mark(1000000);
|
||||
do {
|
||||
c = this.next();
|
||||
if (c == 0) {
|
||||
// in some readers, reset() may throw an exception if
|
||||
// the remaining portion of the input is greater than
|
||||
// the mark size (1,000,000 above).
|
||||
this.reader.reset();
|
||||
this.index = startIndex;
|
||||
this.character = startCharacter;
|
||||
this.line = startLine;
|
||||
return 0;
|
||||
}
|
||||
} while (c != to);
|
||||
this.reader.mark(1);
|
||||
} catch (IOException exception) {
|
||||
throw new JSONException(exception);
|
||||
}
|
||||
this.back();
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a JSONException to signal a syntax error.
|
||||
*
|
||||
* @param message The error message.
|
||||
* @return A JSONException object, suitable for throwing
|
||||
*/
|
||||
public JSONException syntaxError(String message) {
|
||||
return new JSONException(message + this.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a JSONException to signal a syntax error.
|
||||
*
|
||||
* @param message The error message.
|
||||
* @param causedBy The throwable that caused the error.
|
||||
* @return A JSONException object, suitable for throwing
|
||||
*/
|
||||
public JSONException syntaxError(String message, Throwable causedBy) {
|
||||
return new JSONException(message + this.toString(), causedBy);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a printable string of this JSONTokener.
|
||||
*
|
||||
* @return " at {index} [character {character} line {line}]"
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return " at " + this.index + " [character " + this.character + " line " +
|
||||
this.line + "]";
|
||||
}
|
||||
}
|
413
src/main/java/org/json/JSONWriter.java
Normal file
413
src/main/java/org/json/JSONWriter.java
Normal file
|
@ -0,0 +1,413 @@
|
|||
package org.json;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
/*
|
||||
Copyright (c) 2006 JSON.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
The Software shall be used for Good, not Evil.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* JSONWriter provides a quick and convenient way of producing JSON text.
|
||||
* The texts produced strictly conform to JSON syntax rules. No whitespace is
|
||||
* added, so the results are ready for transmission or storage. Each instance of
|
||||
* JSONWriter can produce one JSON text.
|
||||
* <p>
|
||||
* A JSONWriter instance provides a <code>value</code> method for appending
|
||||
* values to the
|
||||
* text, and a <code>key</code>
|
||||
* method for adding keys before values in objects. There are <code>array</code>
|
||||
* and <code>endArray</code> methods that make and bound array values, and
|
||||
* <code>object</code> and <code>endObject</code> methods which make and bound
|
||||
* object values. All of these methods return the JSONWriter instance,
|
||||
* permitting a cascade style. For example, <pre>
|
||||
* new JSONWriter(myWriter)
|
||||
* .object()
|
||||
* .key("JSON")
|
||||
* .value("Hello, World!")
|
||||
* .endObject();</pre> which writes <pre>
|
||||
* {"JSON":"Hello, World!"}</pre>
|
||||
* <p>
|
||||
* The first method called must be <code>array</code> or <code>object</code>.
|
||||
* There are no methods for adding commas or colons. JSONWriter adds them for
|
||||
* you. Objects and arrays can be nested up to 200 levels deep.
|
||||
* <p>
|
||||
* This can sometimes be easier than using a JSONObject to build a string.
|
||||
* @author JSON.org
|
||||
* @version 2016-08-08
|
||||
*/
|
||||
public class JSONWriter {
|
||||
private static final int maxdepth = 200;
|
||||
|
||||
/**
|
||||
* The comma flag determines if a comma should be output before the next
|
||||
* value.
|
||||
*/
|
||||
private boolean comma;
|
||||
|
||||
/**
|
||||
* The current mode. Values:
|
||||
* 'a' (array),
|
||||
* 'd' (done),
|
||||
* 'i' (initial),
|
||||
* 'k' (key),
|
||||
* 'o' (object).
|
||||
*/
|
||||
protected char mode;
|
||||
|
||||
/**
|
||||
* The object/array stack.
|
||||
*/
|
||||
private final JSONObject stack[];
|
||||
|
||||
/**
|
||||
* The stack top index. A value of 0 indicates that the stack is empty.
|
||||
*/
|
||||
private int top;
|
||||
|
||||
/**
|
||||
* The writer that will receive the output.
|
||||
*/
|
||||
protected Appendable writer;
|
||||
|
||||
/**
|
||||
* Make a fresh JSONWriter. It can be used to build one JSON text.
|
||||
*/
|
||||
public JSONWriter(Appendable w) {
|
||||
this.comma = false;
|
||||
this.mode = 'i';
|
||||
this.stack = new JSONObject[maxdepth];
|
||||
this.top = 0;
|
||||
this.writer = w;
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a value.
|
||||
* @param string A string value.
|
||||
* @return this
|
||||
* @throws JSONException If the value is out of sequence.
|
||||
*/
|
||||
private JSONWriter append(String string) throws JSONException {
|
||||
if (string == null) {
|
||||
throw new JSONException("Null pointer");
|
||||
}
|
||||
if (this.mode == 'o' || this.mode == 'a') {
|
||||
try {
|
||||
if (this.comma && this.mode == 'a') {
|
||||
this.writer.append(',');
|
||||
}
|
||||
this.writer.append(string);
|
||||
} catch (IOException e) {
|
||||
// Android as of API 25 does not support this exception constructor
|
||||
// however we won't worry about it. If an exception is happening here
|
||||
// it will just throw a "Method not found" exception instead.
|
||||
throw new JSONException(e);
|
||||
}
|
||||
if (this.mode == 'o') {
|
||||
this.mode = 'k';
|
||||
}
|
||||
this.comma = true;
|
||||
return this;
|
||||
}
|
||||
throw new JSONException("Value out of sequence.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Begin appending a new array. All values until the balancing
|
||||
* <code>endArray</code> will be appended to this array. The
|
||||
* <code>endArray</code> method must be called to mark the array's end.
|
||||
* @return this
|
||||
* @throws JSONException If the nesting is too deep, or if the object is
|
||||
* started in the wrong place (for example as a key or after the end of the
|
||||
* outermost array or object).
|
||||
*/
|
||||
public JSONWriter array() throws JSONException {
|
||||
if (this.mode == 'i' || this.mode == 'o' || this.mode == 'a') {
|
||||
this.push(null);
|
||||
this.append("[");
|
||||
this.comma = false;
|
||||
return this;
|
||||
}
|
||||
throw new JSONException("Misplaced array.");
|
||||
}
|
||||
|
||||
/**
|
||||
* End something.
|
||||
* @param m Mode
|
||||
* @param c Closing character
|
||||
* @return this
|
||||
* @throws JSONException If unbalanced.
|
||||
*/
|
||||
private JSONWriter end(char m, char c) throws JSONException {
|
||||
if (this.mode != m) {
|
||||
throw new JSONException(m == 'a'
|
||||
? "Misplaced endArray."
|
||||
: "Misplaced endObject.");
|
||||
}
|
||||
this.pop(m);
|
||||
try {
|
||||
this.writer.append(c);
|
||||
} catch (IOException e) {
|
||||
// Android as of API 25 does not support this exception constructor
|
||||
// however we won't worry about it. If an exception is happening here
|
||||
// it will just throw a "Method not found" exception instead.
|
||||
throw new JSONException(e);
|
||||
}
|
||||
this.comma = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* End an array. This method most be called to balance calls to
|
||||
* <code>array</code>.
|
||||
* @return this
|
||||
* @throws JSONException If incorrectly nested.
|
||||
*/
|
||||
public JSONWriter endArray() throws JSONException {
|
||||
return this.end('a', ']');
|
||||
}
|
||||
|
||||
/**
|
||||
* End an object. This method most be called to balance calls to
|
||||
* <code>object</code>.
|
||||
* @return this
|
||||
* @throws JSONException If incorrectly nested.
|
||||
*/
|
||||
public JSONWriter endObject() throws JSONException {
|
||||
return this.end('k', '}');
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a key. The key will be associated with the next value. In an
|
||||
* object, every value must be preceded by a key.
|
||||
* @param string A key string.
|
||||
* @return this
|
||||
* @throws JSONException If the key is out of place. For example, keys
|
||||
* do not belong in arrays or if the key is null.
|
||||
*/
|
||||
public JSONWriter key(String string) throws JSONException {
|
||||
if (string == null) {
|
||||
throw new JSONException("Null key.");
|
||||
}
|
||||
if (this.mode == 'k') {
|
||||
try {
|
||||
JSONObject topObject = this.stack[this.top - 1];
|
||||
// don't use the built in putOnce method to maintain Android support
|
||||
if(topObject.has(string)) {
|
||||
throw new JSONException("Duplicate key \"" + string + "\"");
|
||||
}
|
||||
topObject.put(string, true);
|
||||
if (this.comma) {
|
||||
this.writer.append(',');
|
||||
}
|
||||
this.writer.append(JSONObject.quote(string));
|
||||
this.writer.append(':');
|
||||
this.comma = false;
|
||||
this.mode = 'o';
|
||||
return this;
|
||||
} catch (IOException e) {
|
||||
// Android as of API 25 does not support this exception constructor
|
||||
// however we won't worry about it. If an exception is happening here
|
||||
// it will just throw a "Method not found" exception instead.
|
||||
throw new JSONException(e);
|
||||
}
|
||||
}
|
||||
throw new JSONException("Misplaced key.");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Begin appending a new object. All keys and values until the balancing
|
||||
* <code>endObject</code> will be appended to this object. The
|
||||
* <code>endObject</code> method must be called to mark the object's end.
|
||||
* @return this
|
||||
* @throws JSONException If the nesting is too deep, or if the object is
|
||||
* started in the wrong place (for example as a key or after the end of the
|
||||
* outermost array or object).
|
||||
*/
|
||||
public JSONWriter object() throws JSONException {
|
||||
if (this.mode == 'i') {
|
||||
this.mode = 'o';
|
||||
}
|
||||
if (this.mode == 'o' || this.mode == 'a') {
|
||||
this.append("{");
|
||||
this.push(new JSONObject());
|
||||
this.comma = false;
|
||||
return this;
|
||||
}
|
||||
throw new JSONException("Misplaced object.");
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Pop an array or object scope.
|
||||
* @param c The scope to close.
|
||||
* @throws JSONException If nesting is wrong.
|
||||
*/
|
||||
private void pop(char c) throws JSONException {
|
||||
if (this.top <= 0) {
|
||||
throw new JSONException("Nesting error.");
|
||||
}
|
||||
char m = this.stack[this.top - 1] == null ? 'a' : 'k';
|
||||
if (m != c) {
|
||||
throw new JSONException("Nesting error.");
|
||||
}
|
||||
this.top -= 1;
|
||||
this.mode = this.top == 0
|
||||
? 'd'
|
||||
: this.stack[this.top - 1] == null
|
||||
? 'a'
|
||||
: 'k';
|
||||
}
|
||||
|
||||
/**
|
||||
* Push an array or object scope.
|
||||
* @param jo The scope to open.
|
||||
* @throws JSONException If nesting is too deep.
|
||||
*/
|
||||
private void push(JSONObject jo) throws JSONException {
|
||||
if (this.top >= maxdepth) {
|
||||
throw new JSONException("Nesting too deep.");
|
||||
}
|
||||
this.stack[this.top] = jo;
|
||||
this.mode = jo == null ? 'a' : 'k';
|
||||
this.top += 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a JSON text of an Object value. If the object has an
|
||||
* value.toJSONString() method, then that method will be used to produce the
|
||||
* JSON text. The method is required to produce a strictly conforming text.
|
||||
* If the object does not contain a toJSONString method (which is the most
|
||||
* common case), then a text will be produced by other means. If the value
|
||||
* is an array or Collection, then a JSONArray will be made from it and its
|
||||
* toJSONString method will be called. If the value is a MAP, then a
|
||||
* JSONObject will be made from it and its toJSONString method will be
|
||||
* called. Otherwise, the value's toString method will be called, and the
|
||||
* result will be quoted.
|
||||
*
|
||||
* <p>
|
||||
* Warning: This method assumes that the data structure is acyclical.
|
||||
*
|
||||
* @param value
|
||||
* The value to be serialized.
|
||||
* @return a printable, displayable, transmittable representation of the
|
||||
* object, beginning with <code>{</code> <small>(left
|
||||
* brace)</small> and ending with <code>}</code> <small>(right
|
||||
* brace)</small>.
|
||||
* @throws JSONException
|
||||
* If the value is or contains an invalid number.
|
||||
*/
|
||||
public static String valueToString(Object value) throws JSONException {
|
||||
if (value == null || value.equals(null)) {
|
||||
return "null";
|
||||
}
|
||||
if (value instanceof JSONString) {
|
||||
String object;
|
||||
try {
|
||||
object = ((JSONString) value).toJSONString();
|
||||
} catch (Exception e) {
|
||||
throw new JSONException(e);
|
||||
}
|
||||
if (object != null) {
|
||||
return object;
|
||||
}
|
||||
throw new JSONException("Bad value from toJSONString: " + object);
|
||||
}
|
||||
if (value instanceof Number) {
|
||||
// not all Numbers may match actual JSON Numbers. i.e. Fractions or Complex
|
||||
final String numberAsString = JSONObject.numberToString((Number) value);
|
||||
if(JSONObject.NUMBER_PATTERN.matcher(numberAsString).matches()) {
|
||||
// Close enough to a JSON number that we will return it unquoted
|
||||
return numberAsString;
|
||||
}
|
||||
// The Number value is not a valid JSON number.
|
||||
// Instead we will quote it as a string
|
||||
return JSONObject.quote(numberAsString);
|
||||
}
|
||||
if (value instanceof Boolean || value instanceof JSONObject
|
||||
|| value instanceof JSONArray) {
|
||||
return value.toString();
|
||||
}
|
||||
if (value instanceof Map) {
|
||||
Map<?, ?> map = (Map<?, ?>) value;
|
||||
return new JSONObject(map).toString();
|
||||
}
|
||||
if (value instanceof Collection) {
|
||||
Collection<?> coll = (Collection<?>) value;
|
||||
return new JSONArray(coll).toString();
|
||||
}
|
||||
if (value.getClass().isArray()) {
|
||||
return new JSONArray(value).toString();
|
||||
}
|
||||
if(value instanceof Enum<?>){
|
||||
return JSONObject.quote(((Enum<?>)value).name());
|
||||
}
|
||||
return JSONObject.quote(value.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Append either the value <code>true</code> or the value
|
||||
* <code>false</code>.
|
||||
* @param b A boolean.
|
||||
* @return this
|
||||
* @throws JSONException
|
||||
*/
|
||||
public JSONWriter value(boolean b) throws JSONException {
|
||||
return this.append(b ? "true" : "false");
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a double value.
|
||||
* @param d A double.
|
||||
* @return this
|
||||
* @throws JSONException If the number is not finite.
|
||||
*/
|
||||
public JSONWriter value(double d) throws JSONException {
|
||||
return this.value(Double.valueOf(d));
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a long value.
|
||||
* @param l A long.
|
||||
* @return this
|
||||
* @throws JSONException
|
||||
*/
|
||||
public JSONWriter value(long l) throws JSONException {
|
||||
return this.append(Long.toString(l));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Append an object value.
|
||||
* @param object The object to append. It can be null, or a Boolean, Number,
|
||||
* String, JSONObject, or JSONArray, or an object that implements JSONString.
|
||||
* @return this
|
||||
* @throws JSONException If the value is out of sequence.
|
||||
*/
|
||||
public JSONWriter value(Object object) throws JSONException {
|
||||
return this.append(valueToString(object));
|
||||
}
|
||||
}
|
0
src/main/resources/lang.yml
Normal file
0
src/main/resources/lang.yml
Normal file
4
src/main/resources/plugin.yml
Normal file
4
src/main/resources/plugin.yml
Normal file
|
@ -0,0 +1,4 @@
|
|||
name: AuLib
|
||||
main: com.io.yutian.aulib.AuLib
|
||||
version: 1.0
|
||||
author: SuperYuTian
|
5163
src/main/resources/zh_cn.json
Normal file
5163
src/main/resources/zh_cn.json
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user