Taboolib 5.0 fully refactored & Not a plugin now.

This commit is contained in:
坏黑
2019-07-06 00:17:54 +08:00
parent dfae3001ef
commit ab3ed6bebe
335 changed files with 4225 additions and 12881 deletions

View File

@@ -0,0 +1,11 @@
package io.izzel.taboolib.module.ai;
/**
* @Author sky
* @Since 2018-09-21 13:06
*/
public interface PathfinderCreator {
Object createPathfinderGoal(SimpleAi ai);
}

View File

@@ -0,0 +1,66 @@
package io.izzel.taboolib.module.ai;
import org.bukkit.Location;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
/**
* @Author sky
* @Since 2018-09-20 20:47
*/
public abstract class PathfinderExecutor {
public abstract Object getEntityInsentient(LivingEntity entity);
public abstract Object getNavigation(LivingEntity entity);
public abstract Object getControllerJump(LivingEntity entity);
public abstract Object getControllerMove(LivingEntity entity);
public abstract Object getControllerLook(LivingEntity entity);
public abstract Object getGoalSelector(LivingEntity entity);
public abstract Object getTargetSelector(LivingEntity entity);
public abstract Object getPathEntity(LivingEntity entity);
public abstract void setPathEntity(LivingEntity entity, Object pathEntity);
public abstract void setGoalAi(LivingEntity entity, SimpleAi ai, int priority);
public abstract void setTargetAi(LivingEntity entity, SimpleAi ai, int priority);
public abstract void clearGoalAi(LivingEntity entity);
public abstract void clearTargetAi(LivingEntity entity);
public abstract Iterable getGoalAi(LivingEntity entity);
public abstract Iterable getTargetAi(LivingEntity entity);
public abstract void setGoalAi(LivingEntity entity, Iterable ai);
public abstract void setTargetAi(LivingEntity entity, Iterable ai);
public abstract boolean navigationMove(LivingEntity entity, Location location);
public abstract boolean navigationMove(LivingEntity entity, Location location, double speed);
public abstract boolean navigationMove(LivingEntity entity, LivingEntity target);
public abstract boolean navigationMove(LivingEntity entity, LivingEntity target, double speed);
public abstract boolean navigationReach(LivingEntity entity);
public abstract void controllerLookAt(LivingEntity entity, Location target);
public abstract void controllerLookAt(LivingEntity entity, Entity target);
public abstract void controllerJumpReady(LivingEntity entity);
public abstract boolean controllerJumpCurrent(LivingEntity entity);
public abstract void setFollowRange(LivingEntity entity, double value);
}

View File

@@ -0,0 +1,23 @@
package io.izzel.taboolib.module.ai;
/**
* @Author sky
* @Since 2018-09-19 19:42
*/
public abstract class SimpleAi {
public abstract boolean shouldExecute();
public boolean continueExecute() {
return shouldExecute();
}
public void startTask() {
}
public void resetTask() {
}
public void updateTask() {
}
}

View File

@@ -0,0 +1,38 @@
package io.izzel.taboolib.module.ai;
import io.izzel.taboolib.module.inject.TFunction;
import io.izzel.taboolib.module.lite.SimpleVersionControl;
/**
* @Author sky
* @Since 2018-09-19 20:31
*/
@TFunction(enable = "init")
public class SimpleAiSelector {
private static PathfinderCreator internalPathfinderCreator;
private static PathfinderExecutor internalPathfinderExecutor;
static void init() {
try {
internalPathfinderCreator = (PathfinderCreator) SimpleVersionControl.createNMS("io.izzel.taboolib.module.ai.internal.InternalPathfinderCreator").translate().newInstance();
internalPathfinderExecutor = (PathfinderExecutor) SimpleVersionControl.createNMS("io.izzel.taboolib.module.ai.internal.InternalPathfinderExecutor").translate().newInstance();
} catch (Exception e) {
e.printStackTrace();
}
}
// *********************************
//
// Getter and Setter
//
// *********************************
public static PathfinderExecutor getExecutor() {
return internalPathfinderExecutor;
}
public static PathfinderCreator getCreator() {
return internalPathfinderCreator;
}
}

View File

@@ -0,0 +1,52 @@
package io.izzel.taboolib.module.ai.internal;
import io.izzel.taboolib.module.ai.PathfinderCreator;
import io.izzel.taboolib.module.ai.SimpleAi;
/**
* 该类仅用作生成 ASM 代码,无任何意义
*
* @Author sky
* @Since 2018-09-19 22:31
*/
public class InternalPathfinderCreator extends net.minecraft.server.v1_8_R3.PathfinderGoal implements PathfinderCreator {
private SimpleAi simpleAI;
public InternalPathfinderCreator() {
}
public InternalPathfinderCreator(SimpleAi ai) {
this.simpleAI = ai;
}
@Override
public Object createPathfinderGoal(SimpleAi ai) {
return new InternalPathfinderCreator(ai);
}
@Override
public boolean a() {
return simpleAI.shouldExecute();
}
@Override
public boolean b() {
return simpleAI.continueExecute();
}
@Override
public void c() {
simpleAI.startTask();
}
@Override
public void d() {
simpleAI.resetTask();
}
@Override
public void e() {
simpleAI.updateTask();
}
}

View File

@@ -0,0 +1,224 @@
package io.izzel.taboolib.module.ai.internal;
import io.izzel.taboolib.module.ai.PathfinderExecutor;
import io.izzel.taboolib.module.ai.SimpleAi;
import io.izzel.taboolib.module.ai.SimpleAiSelector;
import io.izzel.taboolib.module.lite.SimpleReflection;
import net.minecraft.server.v1_8_R3.*;
import org.bukkit.Location;
import org.bukkit.craftbukkit.v1_8_R3.entity.CraftEntity;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import java.lang.reflect.Field;
import java.util.Collection;
/**
* 该类仅用作生成 ASM 代码,无任何意义
*
* @Author sky
* @Since 2018-09-20 20:57
*/
public class InternalPathfinderExecutor extends PathfinderExecutor {
private Field pathEntity;
private Field pathfinderGoalSelectorSet;
private Field controllerJumpCurrent;
public InternalPathfinderExecutor() {
try {
SimpleReflection.saveField(PathfinderGoalSelector.class);
SimpleReflection.saveField(ControllerJump.class);
pathfinderGoalSelectorSet =SimpleReflection.getField(PathfinderGoalSelector.class, "b");
controllerJumpCurrent = SimpleReflection.getField(ControllerJump.class, "a");
} catch (Exception e) {
e.printStackTrace();
}
try {
SimpleReflection.saveField(NavigationAbstract.class);
for (Field field : SimpleReflection.getFields(NavigationAbstract.class).values()) {
if (field.getType().equals(PathEntity.class)) {
pathEntity = field;
return;
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public Object getEntityInsentient(LivingEntity entity) {
return ((CraftEntity) entity).getHandle();
}
@Override
public Object getNavigation(LivingEntity entity) {
return ((EntityInsentient) getEntityInsentient(entity)).getNavigation();
}
@Override
public Object getControllerJump(LivingEntity entity) {
return ((EntityInsentient) getEntityInsentient(entity)).getControllerJump();
}
@Override
public Object getControllerMove(LivingEntity entity) {
return ((EntityInsentient) getEntityInsentient(entity)).getControllerMove();
}
@Override
public Object getControllerLook(LivingEntity entity) {
return ((EntityInsentient) getEntityInsentient(entity)).getControllerLook();
}
@Override
public Object getGoalSelector(LivingEntity entity) {
return ((EntityInsentient) getEntityInsentient(entity)).goalSelector;
}
@Override
public Object getTargetSelector(LivingEntity entity) {
return ((EntityInsentient) getEntityInsentient(entity)).targetSelector;
}
@Override
public Object getPathEntity(LivingEntity entity) {
try {
return pathEntity.get(getNavigation(entity));
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Override
public void setPathEntity(LivingEntity entity, Object pathEntity) {
try {
this.pathEntity.set(getNavigation(entity), pathEntity);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void setGoalAi(LivingEntity entity, SimpleAi ai, int priority) {
((EntityInsentient) getEntityInsentient(entity)).goalSelector.a(priority, (PathfinderGoal) SimpleAiSelector.getCreator().createPathfinderGoal(ai));
}
@Override
public void setTargetAi(LivingEntity entity, SimpleAi ai, int priority) {
((EntityInsentient) getEntityInsentient(entity)).targetSelector.a(priority, (PathfinderGoal) SimpleAiSelector.getCreator().createPathfinderGoal(ai));
}
@Override
public void clearGoalAi(LivingEntity entity) {
try {
((Collection) pathfinderGoalSelectorSet.get(((EntityInsentient) getEntityInsentient(entity)).goalSelector)).clear();
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void clearTargetAi(LivingEntity entity) {
try {
((Collection) pathfinderGoalSelectorSet.get(((EntityInsentient) getEntityInsentient(entity)).targetSelector)).clear();
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public Iterable getGoalAi(LivingEntity entity) {
try {
return ((Collection) pathfinderGoalSelectorSet.get(((EntityInsentient) getEntityInsentient(entity)).goalSelector));
} catch (Throwable t) {
t.printStackTrace();
}
return null;
}
@Override
public Iterable getTargetAi(LivingEntity entity) {
try {
return ((Collection) pathfinderGoalSelectorSet.get(((EntityInsentient) getEntityInsentient(entity)).targetSelector));
} catch (Throwable t) {
t.printStackTrace();
}
return null;
}
@Override
public void setGoalAi(LivingEntity entity, Iterable ai) {
try {
pathfinderGoalSelectorSet.set(((EntityInsentient) getEntityInsentient(entity)).goalSelector, ai);
} catch (Throwable t) {
t.printStackTrace();
}
}
@Override
public void setTargetAi(LivingEntity entity, Iterable ai) {
try {
pathfinderGoalSelectorSet.set(((EntityInsentient) getEntityInsentient(entity)).targetSelector, ai);
} catch (Throwable t) {
t.printStackTrace();
}
}
@Override
public boolean navigationMove(LivingEntity entity, Location location) {
return navigationMove(entity, location, 0.6);
}
@Override
public boolean navigationMove(LivingEntity entity, Location location, double speed) {
return ((Navigation) getNavigation(entity)).a(location.getX(), location.getY(), location.getZ(), speed);
}
@Override
public boolean navigationMove(LivingEntity entity, LivingEntity target) {
return navigationMove(entity, target, 0.6);
}
@Override
public boolean navigationMove(LivingEntity entity, LivingEntity target, double speed) {
return ((Navigation) getNavigation(entity)).a(((CraftEntity) target).getHandle(), speed);
}
@Override
public boolean navigationReach(LivingEntity entity) {
Object pathEntity = getPathEntity(entity);
return pathEntity == null || ((PathEntity) pathEntity).b();
}
@Override
public void controllerLookAt(LivingEntity entity, Location target) {
((ControllerLook) getControllerLook(entity)).a(target.getX(), target.getY(), target.getZ(), 10, 40);
}
@Override
public void controllerLookAt(LivingEntity entity, Entity target) {
((ControllerLook) getControllerLook(entity)).a(((CraftEntity) target).getHandle(), 10, 40);
}
@Override
public void controllerJumpReady(LivingEntity entity) {
((ControllerJump) getControllerJump(entity)).a();
}
@Override
public boolean controllerJumpCurrent(LivingEntity entity) {
try {
return controllerJumpCurrent.getBoolean(getControllerJump(entity));
} catch (Exception ignored) {
return false;
}
}
@Override
public void setFollowRange(LivingEntity entity, double value) {
((EntityInsentient) getEntityInsentient(entity)).getAttributeInstance(GenericAttributes.FOLLOW_RANGE).setValue(value);
}
}

View File

@@ -0,0 +1,27 @@
package io.izzel.taboolib.module.command;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @Author sky
* @Since 2018-08-23 20:34
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface TCommand {
String name();
String permission() default "";
String permissionMessage() default "";
String description() default "";
String usage() default "";
String[] aliases() default "";
}

View File

@@ -0,0 +1,156 @@
package io.izzel.taboolib.module.command;
import io.izzel.taboolib.TabooLibAPI;
import io.izzel.taboolib.locale.TLocale;
import io.izzel.taboolib.module.command.base.BaseMainCommand;
import io.izzel.taboolib.module.inject.TFunction;
import io.izzel.taboolib.module.lite.SimpleReflection;
import io.izzel.taboolib.util.ArrayUtil;
import io.izzel.taboolib.util.Files;
import io.izzel.taboolib.util.Reflection;
import org.bukkit.Bukkit;
import org.bukkit.command.*;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.SimplePluginManager;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* @Author sky
* @Since 2018-05-23 2:43
*/
@TFunction(enable = "init")
public class TCommandHandler {
private static SimpleCommandMap commandMap;
private static Map<String, Command> knownCommands;
static void init() {
SimpleReflection.saveField(SimplePluginManager.class, "commandMap");
SimpleReflection.saveField(SimpleCommandMap.class, "knownCommands");
commandMap = (SimpleCommandMap) SimpleReflection.getFieldValue(SimplePluginManager.class, Bukkit.getPluginManager(), "commandMap");
knownCommands = (Map<String, Command>) SimpleReflection.getFieldValue(SimpleCommandMap.class, commandMap, "knownCommands");
}
public static boolean registerPluginCommand(Plugin plugin, String command, CommandExecutor commandExecutor) {
return registerPluginCommand(plugin, command, "", "/" + command, new ArrayList<>(), null, null, commandExecutor, null);
}
public static boolean registerPluginCommand(Plugin plugin, String command, CommandExecutor commandExecutor, TabCompleter tabCompleter) {
return registerPluginCommand(plugin, command, "", "/" + command, new ArrayList<>(), null, null, commandExecutor, tabCompleter);
}
public static boolean registerPluginCommand(Plugin plugin, String command, String description, CommandExecutor commandExecutor, TabCompleter tabCompleter) {
return registerPluginCommand(plugin, command, description, "/" + command, new ArrayList<>(), null, null, commandExecutor, tabCompleter);
}
public static boolean registerPluginCommand(Plugin plugin, String command, String description, String usage, CommandExecutor commandExecutor, TabCompleter tabCompleter) {
return registerPluginCommand(plugin, command, description, usage, new ArrayList<>(), null, null, commandExecutor, tabCompleter);
}
public static boolean registerPluginCommand(Plugin plugin, String command, String description, String usage, List<String> aliases, CommandExecutor commandExecutor, TabCompleter tabCompleter) {
return registerPluginCommand(plugin, command, description, usage, aliases, null, null, commandExecutor, tabCompleter);
}
/**
* 获取插件注册的命令
*/
public static Command getPluginCommand(String command) {
return commandMap.getCommand(command);
}
/**
* 向服务端动态注册命令
*
* @param plugin 所属插件
* @param command 命令名称
* @param description 命令描述
* @param usage 命令用法
* @param aliases 别名
* @param permission 权限
* @param permissionMessage 权限提示
* @param commandExecutor 命令执行器
* @param tabCompleter 补全执行器
* @return 注册结果(boolean)
*/
public static boolean registerPluginCommand(Plugin plugin, String command, String description, String usage, List<String> aliases, String permission, String permissionMessage, CommandExecutor commandExecutor, TabCompleter tabCompleter) {
try {
Constructor<PluginCommand> constructor = PluginCommand.class.getDeclaredConstructor(String.class, Plugin.class);
constructor.setAccessible(true);
PluginCommand pluginCommand = constructor.newInstance(command, plugin);
pluginCommand.setExecutor(commandExecutor);
pluginCommand.setTabCompleter(tabCompleter);
Reflection.setValue(pluginCommand, pluginCommand.getClass().getSuperclass(), true, "description", description);
Reflection.setValue(pluginCommand, pluginCommand.getClass().getSuperclass(), true, "usageMessage", usage);
Reflection.setValue(pluginCommand, pluginCommand.getClass().getSuperclass(), true, "aliases", aliases.stream().map(String::toLowerCase).collect(Collectors.toList()));
Reflection.setValue(pluginCommand, pluginCommand.getClass().getSuperclass(), true, "activeAliases", aliases.stream().map(String::toLowerCase).collect(Collectors.toList()));
Reflection.setValue(pluginCommand, pluginCommand.getClass().getSuperclass(), true, "permission", permission);
Reflection.setValue(pluginCommand, pluginCommand.getClass().getSuperclass(), true, "permissionMessage", permissionMessage);
commandMap.register(plugin.getName(), pluginCommand);
TabooLibAPI.debug("Command " + command + " created. (" + plugin.getName() + ")");
return true;
} catch (Exception e) {
TLocale.Logger.error("COMMANDS.INTERNAL.COMMAND-CREATE-FAILED", plugin.getName(), command, e.toString());
e.printStackTrace();
return false;
}
}
/**
* 向服务端注册 BaseMainCommand 类
*
* @param command 命令全称(需在 plugin.yml 内注册)
* @param baseMainCommand 命令对象
* @return {@link BaseMainCommand}
*/
public static BaseMainCommand registerCommand(TCommand tCommand, String command, BaseMainCommand baseMainCommand, Plugin plugin) {
if (Bukkit.getPluginCommand(command) == null) {
registerPluginCommand(
plugin,
command,
ArrayUtil.skipEmpty(tCommand.description(), "Registered by TabooLib."),
ArrayUtil.skipEmpty(tCommand.usage(), "/" + command),
ArrayUtil.skipEmpty(ArrayUtil.asList(tCommand.aliases()), new ArrayList<>()),
ArrayUtil.skipEmpty(tCommand.permission()),
ArrayUtil.skipEmpty(tCommand.permissionMessage()),
baseMainCommand,
baseMainCommand);
}
return BaseMainCommand.createCommandExecutor(command, baseMainCommand);
}
/**
* 注册插件的所有 TCommand 命令
*/
public static void registerCommand(Plugin plugin) {
for (Class pluginClass : Files.getClasses(plugin)) {
if (BaseMainCommand.class.isAssignableFrom(pluginClass) && pluginClass.isAnnotationPresent(TCommand.class)) {
TCommand tCommand = (TCommand) pluginClass.getAnnotation(TCommand.class);
try {
registerCommand(tCommand, tCommand.name(), (BaseMainCommand) pluginClass.newInstance(), plugin);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
// *********************************
//
// Getter and Setter
//
// *********************************
public static SimpleCommandMap getCommandMap() {
return commandMap;
}
public static Map<String, Command> getKnownCommands() {
return knownCommands;
}
}

View File

@@ -0,0 +1,230 @@
package io.izzel.taboolib.module.command.base;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import io.izzel.taboolib.TabooLib;
import io.izzel.taboolib.TabooLibAPI;
import io.izzel.taboolib.Version;
import io.izzel.taboolib.locale.TLocale;
import io.izzel.taboolib.util.ArrayUtil;
import io.izzel.taboolib.util.Strings;
import org.bukkit.Bukkit;
import org.bukkit.command.*;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import org.bukkit.scheduler.BukkitRunnable;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;
/**
* @Author sky
* @Since 2018-05-07 21:38
*/
public abstract class BaseMainCommand implements CommandExecutor, TabExecutor {
private PluginCommand registerCommand;
private List<Class<?>> linkClasses = new CopyOnWriteArrayList<>();
private List<io.izzel.taboolib.module.command.base.BaseSubCommand> subCommands = new CopyOnWriteArrayList<>();
public static BaseMainCommand createCommandExecutor(String command, BaseMainCommand baseMainCommand) {
Preconditions.checkArgument(Bukkit.getPluginCommand(command) != null, "PluginCommand \"" + command + "\" not found");
Preconditions.checkArgument(baseMainCommand != null, "Executor cannot be null");
Preconditions.checkArgument(baseMainCommand.getClass() != BaseMainCommand.class, "Executor can not be \"BaseMainCommand.class\"");
baseMainCommand.setRegisterCommand(Bukkit.getPluginCommand(command));
baseMainCommand.getRegisterCommand().setExecutor(baseMainCommand);
baseMainCommand.getRegisterCommand().setTabCompleter(baseMainCommand);
baseMainCommand.getLinkClasses().add(baseMainCommand.getClass());
baseMainCommand.disguisedPlugin();
loadCommandRegister(baseMainCommand);
return baseMainCommand;
}
public static void loadCommandRegister(BaseMainCommand baseMainCommand) {
List<Method> methods = new ArrayList<>();
List<CommandField> fields = new ArrayList<>();
baseMainCommand.getLinkClasses().forEach(clazz -> java.util.Arrays.stream(clazz.getDeclaredMethods()).filter(method -> method.getAnnotation(CommandRegister.class) != null).forEach(methods::add));
if (methods.size() > 0) {
methods.sort(Comparator.comparingDouble(a -> a.getAnnotation(CommandRegister.class).priority()));
methods.forEach(x -> {
try {
x.setAccessible(true);
x.invoke(baseMainCommand);
} catch (Exception ignored) {
}
});
}
baseMainCommand.getLinkClasses().forEach(clazz -> java.util.Arrays.stream(clazz.getDeclaredFields()).filter(field -> field.getAnnotation(CommandRegister.class) != null && field.getType().equals(io.izzel.taboolib.module.command.base.BaseSubCommand.class)).forEach(field -> fields.add(new CommandField(field, clazz))));
if (fields.size() > 0) {
fields.sort(Comparator.comparingDouble(commandField -> commandField.getField().getAnnotation(CommandRegister.class).priority()));
fields.forEach(commandField -> {
try {
commandField.getField().setAccessible(true);
io.izzel.taboolib.module.command.base.BaseSubCommand subCommand = (io.izzel.taboolib.module.command.base.BaseSubCommand) commandField.getField().get(commandField.getParent().newInstance());
subCommand.setLabel(commandField.getField().getName());
baseMainCommand.registerSubCommand(subCommand);
} catch (Exception ignored) {
}
});
}
if (methods.size() + fields.size() > 0) {
TabooLibAPI.debug("Registered " + (methods.size() + fields.size()) + " sub-command with " + baseMainCommand.getRegisterCommand().getName() + " (" + baseMainCommand.getRegisterCommand().getPlugin().getName() + ")");
}
}
public void setRegisterCommand(PluginCommand registerCommand) {
this.registerCommand = registerCommand;
}
public PluginCommand getRegisterCommand() {
return registerCommand;
}
public List<Class<?>> getLinkClasses() {
return linkClasses;
}
public List<io.izzel.taboolib.module.command.base.BaseSubCommand> getSubCommands() {
return subCommands;
}
public void registerSubCommand(io.izzel.taboolib.module.command.base.BaseSubCommand subCommand) {
if (subCommand != null) {
Preconditions.checkArgument(subCommand.getLabel() != null, "Command label can not be null");
Preconditions.checkArgument(subCommand.getArguments() != null, "Command arguments can not be null");
}
subCommands.add(subCommand);
}
public void onCommandHelp(CommandSender sender, Command command, String label, String[] args) {
sender.sendMessage(getEmptyLine());
sender.sendMessage(getCommandTitle());
sender.sendMessage(getEmptyLine());
subCommands.stream().filter(subCommands -> !hideInHelp(subCommands) && hasPermission(sender, subCommands)).map(subCommand -> subCommand == null ? getEmptyLine() : subCommand.getCommandString(label)).forEach(sender::sendMessage);
sender.sendMessage(getEmptyLine());
}
abstract public String getCommandTitle();
@Override
public List<String> onTabComplete(CommandSender commandSender, Command command, String s, String[] args) {
if (args.length == 1) {
List<String> label = Lists.newArrayList();
subCommands.stream().filter(subCommand -> !hideInHelp(subCommand) && hasPermission(commandSender, subCommand)).forEach(l -> {
label.add(l.getLabel());
label.addAll(Lists.newArrayList(l.getAliases()));
});
return label.stream().filter(l -> args[0].isEmpty() || l.toLowerCase().startsWith(args[0].toLowerCase())).collect(Collectors.toList());
}
for (io.izzel.taboolib.module.command.base.BaseSubCommand subCommand : subCommands) {
CommandArgument[] arguments = subCommand.getArguments();
if (args[0].equalsIgnoreCase(subCommand.getLabel()) && args.length - 1 <= arguments.length) {
CommandTab commandTab = arguments[args.length - 2].getTab();
if (commandTab != null) {
return commandTab.run().stream().filter(l -> args[args.length - 1].isEmpty() || l.toLowerCase().startsWith(args[args.length - 1].toLowerCase())).collect(Collectors.toList());
}
}
}
return null;
}
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if (args.length == 0) {
onCommandHelp(sender, command, label, args);
} else {
for (io.izzel.taboolib.module.command.base.BaseSubCommand subCommand : subCommands) {
if (subCommand == null || !(args[0].equalsIgnoreCase(subCommand.getLabel()) || java.util.Arrays.stream(subCommand.getAliases()).anyMatch(args[0]::equalsIgnoreCase)) || !hasPermission(sender, subCommand)) {
continue;
}
if (!isConfirmType(sender, subCommand.getType())) {
TLocale.sendTo(sender, "COMMANDS.INTERNAL.TYPE-ERROR", args[0], TLocale.asString("COMMANDS.INTERNAL.TYPE-" + subCommand.getType()));
return true;
}
String[] subCommandArgs = ArrayUtil.removeFirst(args);
if (subCommand.isParameterConform(subCommandArgs)) {
subCommand.onCommand(sender, command, label, subCommand.ignoredLabel() ? subCommandArgs : args);
} else {
TLocale.sendTo(sender, "COMMANDS.INTERNAL.ERROR-USAGE", args[0], subCommand.getCommandString(label));
}
return true;
}
new BukkitRunnable() {
@Override
public void run() {
List<io.izzel.taboolib.module.command.base.BaseSubCommand> commandCompute = subCommands.stream().filter(x -> x != null && hasPermission(sender, x)).sorted((b, a) -> Double.compare(Strings.similarDegree(args[0], a.getLabel()), Strings.similarDegree(args[0], b.getLabel()))).collect(Collectors.toList());
if (commandCompute.size() > 0) {
TLocale.sendTo(sender, "COMMANDS.INTERNAL.ERROR-COMMAND", args[0], commandCompute.get(0).getCommandString(label).trim());
}
}
}.runTaskAsynchronously(TabooLib.getPlugin());
}
return true;
}
@Override
public String toString() {
return "registerCommand=" + "BaseMainCommand{" + registerCommand + ", linkClasses=" + linkClasses + ", subCommands=" + subCommands + '}';
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof BaseMainCommand)) {
return false;
}
BaseMainCommand that = (BaseMainCommand) o;
return Objects.equals(getLinkClasses(), that.getLinkClasses()) && Objects.equals(getRegisterCommand(), that.getRegisterCommand()) && Objects.equals(getSubCommands(), that.getSubCommands());
}
@Override
public int hashCode() {
return Objects.hash(getRegisterCommand(), getLinkClasses(), getSubCommands());
}
// *********************************
//
// Private Methods
//
// *********************************
private String getEmptyLine() {
return Version.isAfter(Version.v1_8) ? "" : "~";
}
private boolean isConfirmType(CommandSender sender, CommandType commandType) {
return commandType == CommandType.ALL
|| (sender instanceof Player && commandType == CommandType.PLAYER)
|| (sender instanceof ConsoleCommandSender && commandType == CommandType.CONSOLE);
}
private void disguisedPlugin() {
linkClasses.forEach(clazz -> disguisedPlugin(clazz, registerCommand.getPlugin()));
}
private void disguisedPlugin(Class<?> targetClass, Plugin plugin) {
try {
Field pluginField = targetClass.getClassLoader().getClass().getDeclaredField("plugin");
pluginField.setAccessible(true);
pluginField.set(targetClass.newInstance(), plugin);
} catch (Exception ignored) {
}
}
private boolean hideInHelp(io.izzel.taboolib.module.command.base.BaseSubCommand baseSubCommand) {
return baseSubCommand != null && baseSubCommand.hideInHelp();
}
private boolean hasPermission(CommandSender sender, BaseSubCommand baseSubCommand) {
return baseSubCommand == null || baseSubCommand.getPermission() == null || sender.hasPermission(baseSubCommand.getPermission());
}
}

View File

@@ -0,0 +1,68 @@
package io.izzel.taboolib.module.command.base;
import io.izzel.taboolib.locale.TLocale;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import java.util.Arrays;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
/**
* @author Bkm016
* @since 2018-04-17
*/
public abstract class BaseSubCommand {
private String label;
public void setLabel(String label) {
this.label = label;
}
public String getLabel() {
return label;
}
public String getDescription() {
return null;
}
public String[] getAliases() {
return new String[0];
}
public CommandArgument[] getArguments() {
return new CommandArgument[0];
}
public CommandType getType() {
return CommandType.ALL;
}
public boolean ignoredLabel() {
return true;
}
public boolean requiredPlayer() {
return false;
}
public String getPermission() {
return null;
}
public boolean hideInHelp() {
return false;
}
public boolean isParameterConform(String[] args) {
return IntStream.range(0, getArguments().length).noneMatch(i -> getArguments()[i].isRequired() && (args == null || args.length <= i));
}
public String getCommandString(String label) {
return TLocale.asString(getDescription() == null ? "COMMANDS.INTERNAL.COMMAND-HELP-EMPTY" : "COMMANDS.INTERNAL.COMMAND-HELP", label, getLabel(), Arrays.stream(getArguments()).map(parameter -> parameter.toString() + " ").collect(Collectors.joining()), getDescription());
}
abstract public void onCommand(CommandSender sender, Command command, String label, String[] args);
}

View File

@@ -0,0 +1,70 @@
package io.izzel.taboolib.module.command.base;
import io.izzel.taboolib.locale.TLocale;
import java.util.Objects;
/**
* @author Bkm016
* @since 2018-04-17
*/
public class CommandArgument {
private String name;
private boolean required;
private CommandTab tab;
public String getName() {
return name;
}
public boolean isRequired() {
return required;
}
public CommandTab getTab() {
return tab;
}
public CommandArgument(String name) {
this(name, true);
}
public CommandArgument(String name, CommandTab tab) {
this(name, true, tab);
}
public CommandArgument(String name, boolean required) {
this(name, required, null);
}
public CommandArgument(String name, boolean required, CommandTab tab) {
this.name = name;
this.required = required;
this.tab = tab;
}
@Override
public String toString() {
return required ? TLocale.asString("COMMANDS.INTERNAL.COMMAND-ARGUMENT-REQUIRE", name) : TLocale.asString("COMMANDS.INTERNAL.COMMAND-ARGUMENT", name);
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof CommandArgument)) {
return false;
}
CommandArgument that = (CommandArgument) o;
return isRequired() == that.isRequired() &&
Objects.equals(getName(), that.getName()) &&
Objects.equals(tab, that.tab);
}
@Override
public int hashCode() {
return Objects.hash(getName(), isRequired(), tab);
}
}

View File

@@ -0,0 +1,26 @@
package io.izzel.taboolib.module.command.base;
import java.lang.reflect.Field;
/**
* @Author sky
* @Since 2018-05-23 3:07
*/
public class CommandField {
private final Field field;
private final Class<?> parent;
public CommandField(Field field, Class<?> parent) {
this.field = field;
this.parent = parent;
}
public Field getField() {
return field;
}
public Class<?> getParent() {
return parent;
}
}

View File

@@ -0,0 +1,18 @@
package io.izzel.taboolib.module.command.base;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @Author sky
* @Since 2018-05-09 22:38
*/
@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface CommandRegister {
double priority() default 0;
}

View File

@@ -0,0 +1,14 @@
package io.izzel.taboolib.module.command.base;
import java.util.List;
/**
* 为了防止与 TabExecutor 混淆所以名称改为 CompleterTab
*
* @author sky
*/
public interface CommandTab {
List<String> run();
}

View File

@@ -0,0 +1,11 @@
package io.izzel.taboolib.module.command.base;
/**
* @author Bkm016
* @since 2018-04-17
*/
public enum CommandType {
CONSOLE, PLAYER, ALL
}

View File

@@ -0,0 +1,14 @@
package io.izzel.taboolib.module.command.lite;
import org.bukkit.command.CommandSender;
/**
* 为了防止与 CommandExecutor 混淆所以名称改为 CompleterCommand
*
* @author sky
*/
public interface CompleterCommand {
void execute(CommandSender sender, String[] args);
}

View File

@@ -0,0 +1,16 @@
package io.izzel.taboolib.module.command.lite;
import org.bukkit.command.CommandSender;
import java.util.List;
/**
* 为了防止与 TabExecutor 混淆所以名称改为 CompleterTab
*
* @author sky
*/
public interface CompleterTab {
List<String> execute(CommandSender sender, String[] args);
}

View File

@@ -0,0 +1,177 @@
package io.izzel.taboolib.module.command.lite;
import com.google.common.base.Preconditions;
import io.izzel.taboolib.module.command.TCommandHandler;
import io.izzel.taboolib.util.ArrayUtil;
import org.bukkit.plugin.Plugin;
import java.util.ArrayList;
import java.util.List;
/**
* @Author sky
* @Since 2018-08-27 8:42
* @BuilderLevel 1.0
*/
public class SimpleCommandBuilder {
public static final CompleterTab EMPTY_COMPLETER_TAB = ((sender, args) -> new ArrayList<>());
public static final CompleterCommand EMPTY_COMPLETER_COMMAND = ((sender, args) -> {});
private String command;
private Plugin plugin;
private String description;
private String usage;
private List<String> aliases;
private String permission;
private String permissionMessage;
private CompleterTab completerTab = EMPTY_COMPLETER_TAB;
private CompleterCommand completerCommand = EMPTY_COMPLETER_COMMAND;
private boolean forceRegister;
private boolean build;
SimpleCommandBuilder(String command, Plugin plugin) {
this.command = command;
this.plugin = plugin;
this.description = "";
this.usage = "/" + command;
this.aliases = new ArrayList<>();
this.build = false;
}
public static SimpleCommandBuilder create(String command, Plugin plugin) {
return new SimpleCommandBuilder(command.toLowerCase(), plugin);
}
public SimpleCommandBuilder command(String command) {
this.command = command;
return this;
}
public SimpleCommandBuilder plugin(Plugin plugin) {
this.plugin = plugin;
return this;
}
public SimpleCommandBuilder description(String description) {
this.description = description;
return this;
}
public SimpleCommandBuilder usage(String usage) {
this.usage = usage;
return this;
}
public SimpleCommandBuilder aliases(String... aliases) {
this.aliases = ArrayUtil.asList(aliases);
return this;
}
public SimpleCommandBuilder permission(String permission) {
this.permission = permission;
return this;
}
public SimpleCommandBuilder permissionMessage(String permissionMessage) {
this.permissionMessage = permissionMessage;
return this;
}
public SimpleCommandBuilder execute(CompleterCommand completerCommand) {
this.completerCommand = completerCommand;
return this;
}
public SimpleCommandBuilder tab(CompleterTab completerTab) {
this.completerTab = completerTab;
return this;
}
public SimpleCommandBuilder forceRegister() {
this.forceRegister = true;
return this;
}
public SimpleCommandBuilder build() {
Preconditions.checkNotNull(plugin, "缺少 \"plugin\" 部分");
Preconditions.checkNotNull(command, "缺少 \"command\" 部分");
Preconditions.checkNotNull(completerCommand, "缺少 \"CompleterCommand\" 部分");
Preconditions.checkNotNull(completerTab, "缺少 \"CompleterTab\" 部分");
if (forceRegister) {
TCommandHandler.getKnownCommands().remove(command);
}
TCommandHandler.registerPluginCommand(
plugin,
command,
description,
usage,
aliases,
permission,
permissionMessage,
(sender, command, s, args) -> {
completerCommand.execute(sender, args);
return true;
},
(sender, command, s, args) -> {
try {
return completerTab.execute(sender, args);
} catch (Throwable t) {
t.printStackTrace();
}
return null;
});
build = true;
return this;
}
// *********************************
//
// Getter and Setter
//
// *********************************
public String getCommand() {
return command;
}
public Plugin getPlugin() {
return plugin;
}
public String getDescription() {
return description;
}
public String getUsage() {
return usage;
}
public List<String> getAliases() {
return aliases;
}
public String getPermission() {
return permission;
}
public String getPermissionMessage() {
return permissionMessage;
}
public CompleterTab getCompleterTab() {
return completerTab;
}
public CompleterCommand getCompleterCommand() {
return completerCommand;
}
public boolean isForceRegister() {
return forceRegister;
}
public boolean isBuild() {
return build;
}
}

View File

@@ -0,0 +1,55 @@
package io.izzel.taboolib.module.compat;
import io.izzel.taboolib.module.inject.TFunction;
import net.milkbowl.vault.economy.Economy;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.plugin.RegisteredServiceProvider;
/**
* @Author 坏黑
* @Since 2019-07-05 18:50
*/
@TFunction(enable = "init")
public class EconomyHook {
private static Economy economy;
static void init() {
if (Bukkit.getPluginManager().getPlugin("Vault") == null) {
return;
}
RegisteredServiceProvider<Economy> l = Bukkit.getServer().getServicesManager().getRegistration(Economy.class);
if (l != null) {
economy = l.getProvider();
}
}
public static void remove(OfflinePlayer p, double d) {
economy.withdrawPlayer(p, d);
}
public static void add(OfflinePlayer p, double d) {
economy.depositPlayer(p, d);
}
public static void set(OfflinePlayer p, double d) {
add(p, d - get(p));
}
public static double get(OfflinePlayer p) {
return economy.getBalance(p);
}
public static void create(OfflinePlayer p) {
economy.createPlayerAccount(p);
}
public static boolean exists() {
return economy != null;
}
public static net.milkbowl.vault.economy.Economy getEconomy() {
return economy;
}
}

View File

@@ -0,0 +1,39 @@
package io.izzel.taboolib.module.compat;
import io.izzel.taboolib.module.inject.TFunction;
import net.milkbowl.vault.permission.Permission;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.plugin.RegisteredServiceProvider;
import java.util.Arrays;
@TFunction(enable = "init")
public class PermissionHook {
private static Permission perms;
static void init() {
if (Bukkit.getPluginManager().getPlugin("Vault") == null) {
return;
}
RegisteredServiceProvider<Permission> rsp = Bukkit.getServer().getServicesManager().getRegistration(Permission.class);
perms = rsp.getProvider();
}
public static Permission getPermission() {
return perms;
}
public static void addPermission(Player player, String perm) {
perms.playerAdd(player, perm);
}
public static void removePermission(Player player, String perm) {
perms.playerRemove(player, perm);
}
public static boolean hasPermission(Player player, String perm) {
return perms.playerHas(player, perm) || Arrays.stream(perms.getPlayerGroups(player)).anyMatch(group -> perms.groupHas(player.getWorld(), group, perm));
}
}

View File

@@ -0,0 +1,44 @@
package io.izzel.taboolib.module.compat;
import me.clip.placeholderapi.PlaceholderAPI;
import io.izzel.taboolib.module.inject.TFunction;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@TFunction(enable = "init")
public abstract class PlaceholderHook {
private static PlaceholderHook impl;
static void init() {
if (Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null) {
impl = new PlaceholderImpl();
} else {
impl = new AbstractImpl();
}
}
public static String replace(CommandSender sender, String text) {
return sender instanceof Player ? impl.replace(((Player) sender), text) : text;
}
abstract String replace(Player player, String text);
private static class PlaceholderImpl extends PlaceholderHook {
@Override
String replace(Player player, String text) {
return PlaceholderAPI.setPlaceholders(player, text);
}
}
private static class AbstractImpl extends PlaceholderHook {
@Override
String replace(Player player, String text) {
return text;
}
}
}

View File

@@ -0,0 +1,87 @@
package io.izzel.taboolib.module.compat;
import com.google.common.base.Preconditions;
import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldguard.WorldGuard;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.protection.managers.RegionManager;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.entity.Player;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
/**
* @Author AgarthaLib
*/
public class WorldGuardHook {
public static final WorldGuardHook INSTANCE = new WorldGuardHook();
private WorldGuardPlugin worldGuard;
private Method getRegionManager;
public WorldGuardHook() {
Preconditions.checkNotNull(Bukkit.getServer().getPluginManager().getPlugin("WorldGuard"), "WorldGuard was not found.");
worldGuard = WorldGuardPlugin.inst();
if (!worldGuard.getDescription().getVersion().startsWith("7")) {
try {
getRegionManager = WorldGuardPlugin.class.getDeclaredMethod("getRegionManager", World.class);
getRegionManager.setAccessible(true);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
}
public WorldGuardPlugin getWorldGuard() {
return this.worldGuard;
}
public RegionManager getRegionManager(World world) {
if (worldGuard.getDescription().getVersion().startsWith("7")) {
return WorldGuard.getInstance().getPlatform().getRegionContainer().get(BukkitAdapter.adapt(world));
} else {
try {
return (RegionManager) getRegionManager.invoke(worldGuard, world);
} catch (Throwable t) {
t.printStackTrace();
}
return null;
}
}
public boolean isRegionManagerExists(World world) {
return this.getRegionManager(world) != null;
}
public Collection<String> getRegionIDs(World world) {
return getRegionManager(world).getRegions().keySet();
}
public Collection<ProtectedRegion> getRegions(World world) {
return getRegionManager(world).getRegions().values();
}
public List<String> getRegionsAtLocation(World world, Location location) {
return getRegions(world).stream().filter(protectedRegion -> protectedRegion.contains(location.getBlockX(), location.getBlockY(), location.getBlockZ())).map(ProtectedRegion::getId).collect(Collectors.toList());
}
public ProtectedRegion getRegion(World world, String id) {
RegionManager regionManager = this.getRegionManager(world);
return regionManager != null ? regionManager.getRegions().keySet().stream().filter(key -> key.equalsIgnoreCase(id)).findFirst().map(regionManager::getRegion).orElse(null) : null;
}
public boolean isRegionExists(World world, String id) {
return this.getRegion(world, id) != null;
}
public boolean isPlayerInsideRegion(ProtectedRegion region, Player player) {
Location location = player.getLocation();
return region.contains(location.getBlockX(), location.getBlockY(), location.getBlockZ());
}
}

View File

@@ -0,0 +1,106 @@
package io.izzel.taboolib.module.config;
import com.google.common.collect.Maps;
import io.izzel.taboolib.TabooLib;
import io.izzel.taboolib.TabooLibAPI;
import io.izzel.taboolib.locale.TLocale;
import io.izzel.taboolib.module.logger.TLogger;
import io.izzel.taboolib.util.Files;
import io.izzel.taboolib.util.Ref;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.plugin.Plugin;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
/**
* @Author sky
* @Since 2018-09-08 15:00
*/
public class TConfig extends YamlConfiguration {
private static Map<String, List<File>> files = Maps.newHashMap();
private File file;
private Runnable runnable;
private TConfig(File file, Plugin plugin) {
files.computeIfAbsent(plugin.getName(), name -> new ArrayList<>()).add(file);
this.file = file;
reload();
TConfigWatcher.getInst().addSimpleListener(this.file, this::reload);
TabooLibAPI.debug("Loaded TConfiguration \"" + file.getName() + "\" from Plugin \"" + plugin.getName() + "\"");
}
public static Map<String, List<File>> getFiles() {
return files;
}
public static TConfig create(File file) {
return new TConfig(file, Ref.getCallerPlugin(Ref.getCallerClass(3).orElse(TabooLib.class)));
}
public static TConfig create(File file, Plugin plugin) {
return new TConfig(file, plugin);
}
public static TConfig create(Plugin plugin, String path) {
File file = new File(plugin.getDataFolder(), path);
if (!file.exists()) {
Files.releaseResource(plugin, path, false);
}
return create(file, plugin);
}
public String getStringColored(String path) {
return TLocale.Translate.setColored(getString(path));
}
public String getStringColored(String path, String def) {
return TLocale.Translate.setColored(getString(path, def));
}
public List<String> getStringListColored(String path) {
return TLocale.Translate.setColored(getStringList(path));
}
public void release() {
TConfigWatcher.getInst().removeListener(file);
}
public void reload() {
try {
load(file);
runListener();
} catch (IOException | InvalidConfigurationException e) {
TLogger.getGlobalLogger().warn("Cannot load configuration from stream: " + e.toString());
}
}
// *********************************
//
// Getter and Setter
//
// *********************************
public File getFile() {
return file;
}
public TConfig listener(Runnable runnable) {
this.runnable = runnable;
return this;
}
public void runListener() {
try {
Optional.ofNullable(runnable).ifPresent(Runnable::run);
} catch (Exception e) {
e.printStackTrace();
}
}
}

View File

@@ -0,0 +1,92 @@
package io.izzel.taboolib.module.config;
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.apache.commons.lang3.tuple.Triple;
import java.io.File;
import java.io.IOException;
import java.nio.file.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
/**
* @author lzzelAliz
*/
public class TConfigWatcher {
private static TConfigWatcher configWatcher = new TConfigWatcher();
private final ScheduledExecutorService service = Executors.newScheduledThreadPool(1, new BasicThreadFactory.Builder().namingPattern("TConfigWatcherService-%d").build());
private final Map<WatchService, Triple<File, Object, Consumer<Object>>> map = new HashMap<>();
public TConfigWatcher() {
service.scheduleAtFixedRate(() -> {
synchronized (map) {
map.forEach((service, triple) -> {
WatchKey key;
while ((key = service.poll()) != null) {
for (WatchEvent<?> watchEvent : key.pollEvents()) {
if (triple.getLeft().getName().equals(Objects.toString(watchEvent.context()))) {
triple.getRight().accept(triple.getMiddle());
}
}
key.reset();
}
});
}
}, 1000, 100, TimeUnit.MILLISECONDS);
}
public static TConfigWatcher getInst() {
return configWatcher;
}
public void addSimpleListener(File file, Runnable runnable) {
addListener(file, null, obj -> runnable.run());
}
public void addOnListen(File file, Object obj, Consumer<Object> consumer) {
try {
WatchService service = FileSystems.getDefault().newWatchService();
file.getParentFile().toPath().register(service, StandardWatchEventKinds.ENTRY_MODIFY);
map.putIfAbsent(service, Triple.of(file, obj, consumer));
} catch (IOException e) {
e.printStackTrace();
}
}
@SuppressWarnings("unchecked")
public <T> void addListener(File file, T obj, Consumer<T> consumer) {
addOnListen(file, obj, (Consumer<Object>) consumer);
}
public void removeListener(File file) {
synchronized (map) {
map.entrySet().removeIf(entry -> {
if (entry.getValue().getLeft().equals(file)) {
try {
entry.getKey().close();
} catch (IOException ignored) {
}
return true;
}
return false;
});
}
}
public void unregisterAll() {
service.shutdown();
map.forEach((service, pair) -> {
try {
service.close();
} catch (IOException e) {
e.printStackTrace();
}
});
}
}

View File

@@ -0,0 +1,14 @@
package io.izzel.taboolib.module.dependency;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Dependencies {
Dependency[] value();
}

View File

@@ -0,0 +1,22 @@
package io.izzel.taboolib.module.dependency;
import java.lang.annotation.*;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(Dependencies.class)
public @interface Dependency {
enum Type {PLUGIN, LIBRARY}
Type type();
String plugin() default "";
String maven() default "";
String mavenRepo() default TDependency.MAVEN_REPO;
String url() default "";
}

View File

@@ -0,0 +1,62 @@
package io.izzel.taboolib.module.dependency;
import io.izzel.taboolib.TabooLib;
import io.izzel.taboolib.util.Files;
import java.io.File;
import java.util.Arrays;
public class TDependency {
// 阿里 http://maven.aliyun.com/nexus/content/groups/public
public static final String MAVEN_REPO = "http://repo1.maven.org/maven2";
/**
* 请求一个插件作为依赖,这个插件将会在所有已经添加的 Jenkins 仓库、Maven 仓库寻找
* <p>
* 阻塞线程进行下载/加载
*
* @param args 插件名称,下载地址(可选)
* @return 是否成功加载了依赖
*/
public static boolean requestPlugin(String... args) {
return false;
}
/**
* 请求一个库作为依赖,这个库将会在 Maven Central、oss.sonatype 以及自定义的 Maven 仓库寻找
* <p>
* 阻塞线程进行下载/加载
*
* @param type 依赖名,格式为 groupId:artifactId:version
* @return 是否成功加载库,如果加载成功,插件将可以任意调用使用的类
*/
public static boolean requestLib(String type, String repo, String url) {
// 清理大小为 0 的依赖文件
File libFolder = new File(TabooLib.getPlugin().getDataFolder(), "/libs");
if (libFolder.exists()) {
Arrays.stream(libFolder.listFiles()).filter(listFile -> listFile.length() == 0).forEach(File::delete);
}
if (type.matches(".*:.*:.*")) {
String[] arr = type.split(":");
File file = new File(TabooLib.getPlugin().getDataFolder(), "/libs/" + String.join("-", arr) + ".jar");
if (file.exists()) {
TDependencyLoader.addToPath(TabooLib.getPlugin(), file);
return true;
} else {
if (downloadMaven(repo, arr[0], arr[1], arr[2], file, url)) {
TDependencyLoader.addToPath(TabooLib.getPlugin(), file);
return true;
} else {
return false;
}
}
}
return false;
}
private static boolean downloadMaven(String url, String groupId, String artifactId, String version, File target, String dl) {
Files.toFile(Files.readFromURL(dl.length() == 0 ? url + "/" + groupId.replace('.', '/') + "/" + artifactId + "/" + version + "/" + artifactId + "-" + version + ".jar" : dl, ""), Files.file(target));
return target.length() > 0;
}
}

View File

@@ -0,0 +1,40 @@
package io.izzel.taboolib.module.dependency;
import io.izzel.taboolib.TabooLibAPI;
import io.izzel.taboolib.locale.TLocale;
import org.bukkit.plugin.Plugin;
/**
* @author Izzel_Aliz
*/
public class TDependencyInjector {
public static Dependency[] getDependencies(Class<?> clazz) {
Dependency[] dependencies = new Dependency[0];
Dependencies d = clazz.getAnnotation(Dependencies.class);
if (d != null) {
dependencies = d.value();
}
Dependency d2 = clazz.getAnnotation(Dependency.class);
if (d2 != null) {
dependencies = new Dependency[] {d2};
}
return dependencies;
}
public static void inject(Plugin plugin, Class<?> clazz) {
inject(plugin.getName(), clazz);
}
public static void inject(String name, Class<?> clazz) {
for (Dependency dependency : getDependencies(clazz)) {
if (dependency.type() == Dependency.Type.LIBRARY) {
if (TDependency.requestLib(dependency.maven(), dependency.mavenRepo(), dependency.url())) {
TabooLibAPI.debug(" Loaded " + String.join(":", dependency.maven()) + " (" + name + ")");
} else {
TLocale.Logger.warn("DEPENDENCY.LIBRARY-LOAD-FAIL", name, String.join(":", dependency.maven()));
}
}
}
}
}

View File

@@ -0,0 +1,23 @@
package io.izzel.taboolib.module.inject;
/**
* @author sky
*/
public class Container {
private final Object container;
private final boolean uniqueId;
public Container(Object container, boolean uniqueId) {
this.container = container;
this.uniqueId = uniqueId;
}
public Object getContainer() {
return container;
}
public boolean isUniqueId() {
return uniqueId;
}
}

View File

@@ -0,0 +1,18 @@
package io.izzel.taboolib.module.inject;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @Author sky
* @Since 2018-09-14 23:45
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface PlayerContainer {
boolean uniqueId() default false;
}

View File

@@ -0,0 +1,59 @@
package io.izzel.taboolib.module.inject;
import io.izzel.taboolib.TabooLibLoader;
import io.izzel.taboolib.module.logger.TLogger;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.plugin.Plugin;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* @Author sky
* @Since 2018-09-14 23:45
*/
@TListener
public class PlayerContainerLoader implements Listener, TabooLibLoader.Loader {
static Map<String, List<Container>> pluginContainer = new ConcurrentHashMap<>();
@Override
public void postLoad(Plugin plugin, Class<?> pluginClass) {
for (Field field : pluginClass.getDeclaredFields()) {
PlayerContainer annotation = field.getAnnotation(PlayerContainer.class);
if (annotation == null) {
continue;
}
field.setAccessible(true);
try {
pluginContainer.computeIfAbsent(plugin.getName(), name -> new ArrayList<>()).add(new Container(field.get(pluginClass), annotation.uniqueId()));
} catch (IllegalAccessException ignored) {
}
}
}
@Override
public void unload(Plugin plugin, Class<?> cancelClass) {
pluginContainer.remove(plugin.getName());
}
@EventHandler(priority = EventPriority.MONITOR)
public void onQuit(PlayerQuitEvent e) {
pluginContainer.values().stream().flatMap(Collection::stream).forEach(container -> {
if (container.getContainer() instanceof Map) {
((Map) container.getContainer()).remove(container.isUniqueId() ? e.getPlayer().getUniqueId() : e.getPlayer().getName());
} else if (container.getContainer() instanceof Collection) {
((Collection) container.getContainer()).remove(container.isUniqueId() ? e.getPlayer().getUniqueId() : e.getPlayer().getName());
} else {
TLogger.getGlobalLogger().error("Invalid Container: " + container.getContainer().getClass().getSimpleName());
}
});
}
}

View File

@@ -0,0 +1,19 @@
package io.izzel.taboolib.module.inject;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @Author sky
* @Since 2018-09-08 14:01
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface TFunction {
String enable() default "onEnable";
String disable() default "onDisable";
}

View File

@@ -0,0 +1,58 @@
package io.izzel.taboolib.module.inject;
import io.izzel.taboolib.TabooLibAPI;
import io.izzel.taboolib.TabooLibLoader;
import io.izzel.taboolib.module.logger.TLogger;
import org.bukkit.plugin.Plugin;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
/**
* @Author sky
* @Since 2018-09-08 14:00
*/
public class TFunctionLoader implements TabooLibLoader.Loader {
@Override
public void postLoad(Plugin plugin, Class<?> pluginClass) {
if (pluginClass.isAnnotationPresent(TFunction.class)) {
TFunction function = pluginClass.getAnnotation(TFunction.class);
try {
Method method = pluginClass.getDeclaredMethod(function.enable());
if (!Modifier.isStatic(method.getModifiers())) {
TLogger.getGlobalLogger().error(method.getName() + " is not a static method.");
return;
}
method.setAccessible(true);
method.invoke(null);
TabooLibAPI.debug("Function " + pluginClass.getSimpleName() + " loaded. (" + plugin.getName() + ")");
} catch (NoSuchMethodException ignore) {
} catch (Exception e) {
TLogger.getGlobalLogger().warn("TFunction load Failed: " + pluginClass.getName());
e.printStackTrace();
}
}
}
@Override
public void unload(Plugin plugin, Class<?> pluginClass) {
if (pluginClass.isAnnotationPresent(TFunction.class)) {
TFunction function = pluginClass.getAnnotation(TFunction.class);
try {
Method method = pluginClass.getDeclaredMethod(function.disable());
if (!Modifier.isStatic(method.getModifiers())) {
TLogger.getGlobalLogger().error(method.getName() + " is not a static method.");
return;
}
method.setAccessible(true);
method.invoke(null);
TabooLibAPI.debug("Function " + pluginClass.getSimpleName() + " unloaded. (" + plugin.getName() + ")");
} catch (NoSuchMethodException ignore) {
} catch (Exception e) {
TLogger.getGlobalLogger().warn("TFunction unload Failed: " + pluginClass.getName());
e.printStackTrace();
}
}
}
}

View File

@@ -0,0 +1,18 @@
package io.izzel.taboolib.module.inject;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @Author sky
* @Since 2018-10-05 12:11
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TInject {
String[] value() default {};
}

View File

@@ -0,0 +1,153 @@
package io.izzel.taboolib.module.inject;
import com.google.common.collect.Maps;
import io.izzel.taboolib.TabooLibAPI;
import io.izzel.taboolib.TabooLibLoader;
import io.izzel.taboolib.module.command.lite.SimpleCommandBuilder;
import io.izzel.taboolib.module.config.TConfig;
import io.izzel.taboolib.module.logger.TLogger;
import io.izzel.taboolib.module.packet.TPacketHandler;
import io.izzel.taboolib.module.packet.TPacketListener;
import io.izzel.taboolib.origin.lite.cooldown.Cooldown;
import io.izzel.taboolib.origin.lite.cooldown.Cooldowns;
import org.bukkit.plugin.Plugin;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Map;
/**
* @Author sky
* @Since 2018-10-05 13:40
*/
public class TInjectLoader implements TabooLibLoader.Loader {
private static Map<Class<?>, TInjectTask> injectTypes = Maps.newLinkedHashMap();
static {
// Instance Inject
injectTypes.put(Plugin.class, (plugin, field, args, instance) -> {
try {
field.set(instance, plugin);
} catch (Exception e) {
e.printStackTrace();
}
});
// TLogger Inject
injectTypes.put(TLogger.class, (plugin, field, args, instance) -> {
try {
field.set(instance, args.length == 0 ? TLogger.getUnformatted(plugin) : TLogger.getUnformatted(args[0]));
} catch (Exception e) {
e.printStackTrace();
}
});
// TPacketListener Inject
injectTypes.put(TPacketListener.class, (plugin, field, args, instance) -> {
try {
TPacketHandler.addListener(plugin, ((TPacketListener) field.get(instance)));
} catch (Exception e) {
e.printStackTrace();
}
});
// TConfiguration Inject
injectTypes.put(TConfig.class, (plugin, field, args, instance) -> {
try {
field.set(instance, TConfig.create(plugin, args.length == 0 ? "config.yml" : args[0]));
} catch (Exception e) {
e.printStackTrace();
}
});
// SimpleCommandBuilder Inject
injectTypes.put(SimpleCommandBuilder.class, (plugin, field, args, instance) -> {
try {
SimpleCommandBuilder builder = (SimpleCommandBuilder) field.get(instance);
if (builder.isBuild()) {
TLogger.getGlobalLogger().error("Command was registered. (" + field.getType().getName() + ")");
} else {
if (builder.getPlugin() == null) {
builder.plugin(plugin);
}
builder.build();
}
} catch (Exception e) {
e.printStackTrace();
}
});
// CooldownPack Inject
injectTypes.put(Cooldown.class, (plugin, field, args, instance) -> {
try {
Cooldowns.register((Cooldown) field.get(instance), plugin);
} catch (Throwable t) {
t.printStackTrace();
}
});
}
@Override
public int priority() {
return -999;
}
@Override
public void preLoad(Plugin plugin, Class<?> pluginClass) {
for (Field declaredField : pluginClass.getDeclaredFields()) {
TInject annotation = declaredField.getAnnotation(TInject.class);
// 是否为主类类型
if (annotation == null || !declaredField.getType().equals(plugin.getClass())) {
continue;
}
Object instance = null;
// 如果是非静态类型
if (!Modifier.isStatic(declaredField.getModifiers())) {
// 是否为主类
if (pluginClass.equals(plugin.getClass())) {
instance = plugin;
} else {
TLogger.getGlobalLogger().error(declaredField.getName() + " is not a static field. (" + declaredField.getType().getName() + ")");
continue;
}
}
inject(plugin, declaredField, instance, annotation, injectTypes.get(Plugin.class));
}
}
@Override
public void postLoad(Plugin plugin, Class<?> pluginClass) {
for (Field declaredField : pluginClass.getDeclaredFields()) {
TInject annotation = declaredField.getAnnotation(TInject.class);
if (annotation == null || declaredField.getType().equals(plugin.getClass())) {
continue;
}
Object instance = null;
// 如果是非静态类型
if (!Modifier.isStatic(declaredField.getModifiers())) {
// 是否为主类
if (pluginClass.equals(plugin.getClass())) {
instance = plugin;
} else {
TLogger.getGlobalLogger().error(declaredField.getName() + " is not a static field. (" + declaredField.getType().getName() + ")");
continue;
}
}
TInjectTask tInjectTask = injectTypes.get(declaredField.getType());
if (tInjectTask != null) {
inject(plugin, declaredField, instance, annotation, tInjectTask);
} else {
TLogger.getGlobalLogger().error(declaredField.getName() + " is an invalid inject type. (" + declaredField.getType().getName() + ")");
}
}
}
public void inject(Plugin plugin, Field field, Object instance, TInject annotation, TInjectTask injectTask) {
try {
field.setAccessible(true);
injectTask.run(plugin, field, annotation.value(), instance);
TabooLibAPI.debug(field.getName() + " injected. (" + field.getType().getName() + ")");
} catch (Throwable e) {
TLogger.getGlobalLogger().error(field.getName() + " inject failed: " + e.getMessage() + " (" + field.getType().getName() + ")");
if (e.getMessage() == null) {
e.printStackTrace();
}
}
}
}

View File

@@ -0,0 +1,15 @@
package io.izzel.taboolib.module.inject;
import org.bukkit.plugin.Plugin;
import java.lang.reflect.Field;
/**
* @Author sky
* @Since 2018-10-05 13:41
*/
public interface TInjectTask {
void run(Plugin plugin, Field field, String[] args, Object instance);
}

View File

@@ -0,0 +1,41 @@
package io.izzel.taboolib.module.inject;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @Author sky
* @Since 2018-08-22 13:41
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface TListener {
/**
* 注册时执行的方法名
*/
String register() default "";
/**
* 注销时执行的方法名
*/
String cancel() default "";
/**
* 注册时判断的方法名,需返回布尔值
*/
String condition() default "";
/**
* 注册前判断依赖插件
*/
String[] depend() default "";
/**
* 注册前判断依赖版本
*/
String version() default ">0";
}

View File

@@ -0,0 +1,168 @@
package io.izzel.taboolib.module.inject;
import io.izzel.taboolib.TabooLibAPI;
import io.izzel.taboolib.TabooLibLoader;
import io.izzel.taboolib.Version;
import io.izzel.taboolib.module.logger.TLogger;
import io.izzel.taboolib.origin.cronus.util.StringExpression;
import io.izzel.taboolib.util.Strings;
import io.izzel.taboolib.util.Reflection;
import org.bukkit.Bukkit;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.bukkit.plugin.Plugin;
import java.lang.reflect.Method;
import java.util.*;
/**
* @Author sky
* @Since 2018-08-22 13:48
*/
public class TListenerHandler {
private static HashMap<String, List<Listener>> listeners = new HashMap<>();
/**
* 初始化所有插件的所有监听器
*/
public static void setupListeners() {
for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) {
try {
setupListener(plugin);
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 初始化插件的所有监听器
* 该操作会执行无参构造方法
*
* @param plugin 插件
*/
public static void setupListener(Plugin plugin) {
for (Class<?> pluginClass : TabooLibLoader.getPluginClassSafely(plugin)) {
if (Listener.class.isAssignableFrom(pluginClass) && pluginClass.isAnnotationPresent(TListener.class)) {
try {
TListener tListener = pluginClass.getAnnotation(TListener.class);
// 检查版本
if (!new StringExpression(tListener.version()).isSelect(Version.getCurrentVersion().getVersionInt())) {
continue;
}
// 检查注册条件
if (tListener.depend().length > 0 && !Strings.isBlank(tListener.depend()[0])) {
if (Arrays.stream(tListener.depend()).anyMatch(depend -> Bukkit.getPluginManager().getPlugin(depend) == null)) {
continue;
}
}
// 实例化监听器
Listener listener = plugin.getClass().equals(pluginClass) ? (Listener) plugin : (Listener) Reflection.instantiateObject(pluginClass);
try {
listeners.computeIfAbsent(plugin.getName(), name -> new ArrayList<>()).add(listener);
TabooLibAPI.debug("Listener " + listener.getClass().getSimpleName() + " setup successfully. (" + plugin.getName() + ")");
} catch (Exception e) {
TLogger.getGlobalLogger().warn("TListener setup Failed: " + pluginClass.getName());
e.printStackTrace();
}
} catch (Exception e) {
TabooLibAPI.debug("Listener " + pluginClass.getSimpleName() + "(" + plugin.getName() + ")" + " setup failed: " + e.toString());
}
}
}
}
/**
* 注册所有插件的所有监听器
*/
public static void registerListeners() {
for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) {
try {
registerListener(plugin);
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 注册插件的所有监听器
* 该操作会执行 TListener 注解中的 register() 对应方法
*
* @param plugin 插件
*/
public static void registerListener(Plugin plugin) {
Optional.ofNullable(listeners.get(plugin.getName())).ifPresent(listeners -> {
for (Listener listener : listeners) {
TListener tListener = listener.getClass().getAnnotation(TListener.class);
// 检查注册条件
if (!Strings.isBlank(tListener.condition())) {
try {
Method method = listener.getClass().getDeclaredMethod(tListener.condition());
method.setAccessible(true);
if (!(boolean) method.invoke(listener)) {
continue;
}
} catch (Exception e) {
e.printStackTrace();
}
}
// 执行注册方法
if (!Strings.isBlank(tListener.register())) {
try {
Method method = listener.getClass().getDeclaredMethod(tListener.register());
method.setAccessible(true);
method.invoke(listener);
} catch (Exception e) {
e.printStackTrace();
}
}
// 注册监听
Bukkit.getPluginManager().registerEvents(listener, plugin);
TabooLibAPI.debug("Listener " + listener.getClass().getSimpleName() + " registered. (" + plugin.getName() + ")");
}
});
}
/**
* 注销所有插件的所有监听器
*/
public static void cancelListeners() {
for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) {
try {
cancelListener(plugin);
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 注销插件的所有监听器
* 该操作会执行 TListener 注解中的 cancel() 对应方法
*
* @param plugin 插件
*/
public static void cancelListener(Plugin plugin) {
Optional.ofNullable(listeners.remove(plugin.getName())).ifPresent(listeners -> {
for (Listener listener : listeners) {
HandlerList.unregisterAll(listener);
TListener tListener = listener.getClass().getAnnotation(TListener.class);
if (!Strings.isBlank(tListener.cancel())) {
try {
Method method = listener.getClass().getDeclaredMethod(tListener.cancel());
method.setAccessible(true);
method.invoke(listener);
} catch (Exception e) {
e.printStackTrace();
}
}
}
});
}
public static HashMap<String, List<Listener>> getListeners() {
return listeners;
}
}

View File

@@ -0,0 +1,21 @@
package io.izzel.taboolib.module.inject;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @Author 坏黑
* @Since 2018-12-15 15:07
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TSchedule {
int delay() default 0;
int period() default -1;
boolean async() default false;
}

View File

@@ -0,0 +1,26 @@
package io.izzel.taboolib.module.inject;
import org.bukkit.scheduler.BukkitRunnable;
/**
* @Author 坏黑
* @Since 2018-12-15 15:25
*/
public class TScheduleData {
private final TSchedule annotation;
private final BukkitRunnable runnable;
public TScheduleData(TSchedule annotation, BukkitRunnable runnable) {
this.annotation = annotation;
this.runnable = runnable;
}
public TSchedule getAnnotation() {
return annotation;
}
public BukkitRunnable getRunnable() {
return runnable;
}
}

View File

@@ -0,0 +1,77 @@
package io.izzel.taboolib.module.inject;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import io.izzel.taboolib.TabooLib;
import io.izzel.taboolib.TabooLibLoader;
import io.izzel.taboolib.module.logger.TLogger;
import org.bukkit.plugin.Plugin;
import org.bukkit.scheduler.BukkitRunnable;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.List;
import java.util.Map;
/**
* @Author 坏黑
* @Since 2018-12-15 15:09
*/
public class TScheduleLoader implements TabooLibLoader.Loader {
static Map<String, List<TScheduleData>> schedules = Maps.newHashMap();
public static void run(Plugin plugin, BukkitRunnable runnable, int delay, int period, boolean async) {
if (async) {
runnable.runTaskTimerAsynchronously(plugin, delay, period);
} else {
runnable.runTaskTimer(plugin, delay, period);
}
}
@Override
public void postLoad(Plugin plugin, Class<?> loadClass) {
for (Method method : loadClass.getDeclaredMethods()) {
TSchedule annotation = method.getAnnotation(TSchedule.class);
if (annotation == null) {
continue;
}
Object instance = loadClass.equals(plugin.getClass()) ? plugin : null;
// 如果是非静态类型
if (!Modifier.isStatic(method.getModifiers()) && instance == null) {
// 是否为主类
TLogger.getGlobalLogger().error(method.getName() + " is not a static method.");
continue;
}
method.setAccessible(true);
// 如果是本插件
if (plugin.equals(TabooLib.getPlugin())) {
run(plugin, new BukkitRunnable() {
@Override
public void run() {
try {
method.invoke(instance);
} catch (Throwable t) {
t.printStackTrace();
}
}
}, annotation.delay(), annotation.period(), annotation.async());
}
// 其他插件则添加到列队
else {
schedules.computeIfAbsent(plugin.getName(), n -> Lists.newArrayList()).add(new TScheduleData(annotation, new BukkitRunnable() {
@Override
public void run() {
try {
method.invoke(instance);
} catch (Throwable t) {
t.printStackTrace();
}
}
}));
}
}
}
}

View File

@@ -0,0 +1,193 @@
package io.izzel.taboolib.module.item;
import io.izzel.taboolib.Version;
import io.izzel.taboolib.locale.TLocale;
import io.izzel.taboolib.util.ArrayUtil;
import org.bukkit.Color;
import org.bukkit.Material;
import org.bukkit.OfflinePlayer;
import org.bukkit.block.banner.Pattern;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.EntityType;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.*;
import org.bukkit.potion.PotionData;
import org.bukkit.potion.PotionEffect;
import java.util.List;
/**
* @Author sky
* @Since 2018-08-22 11:37
* @BuilderVersion 1.1
*/
public class ItemBuilder {
private ItemStack itemStack;
private ItemMeta itemMeta;
public ItemBuilder(Material material) {
this(material, 1, 0);
}
public ItemBuilder(Material material, int amount) {
this(material, amount, 0);
}
public ItemBuilder(Material material, int amount, int damage) {
itemStack = new ItemStack(material, amount, (short) damage);
itemMeta = itemStack.getItemMeta();
}
public ItemBuilder(ItemStack itemStack) {
this.itemStack = itemStack;
this.itemMeta = itemStack.getItemMeta();
}
public ItemBuilder(OfflinePlayer player) {
this(Material.SKULL_ITEM, 1, 3);
this.skullOwner(player.getName());
}
public ItemBuilder material(int id) {
itemStack.setType(Material.getMaterial(id));
return this;
}
public ItemBuilder material(String material) {
itemStack.setType(Material.getMaterial(material));
return this;
}
public ItemBuilder material(Material material) {
itemStack.setType(material);
return this;
}
public ItemBuilder amount(int amount) {
itemStack.setAmount(amount);
return this;
}
public ItemBuilder damage(int damage) {
itemStack.setDurability((short) damage);
return this;
}
public ItemBuilder name(String name) {
itemMeta.setDisplayName(name);
return this;
}
public ItemBuilder lore(List<String> lore) {
itemMeta.setLore(lore);
return this;
}
public ItemBuilder lore(String... lore) {
itemMeta.setLore(ArrayUtil.asList(lore));
return this;
}
public ItemBuilder flags(ItemFlag... flags) {
itemMeta.addItemFlags(flags);
return this;
}
public ItemBuilder enchant(Enchantment enchantment, int level) {
return enchant(enchantment, level, false);
}
public ItemBuilder enchant(Enchantment enchantment, int level, boolean bypass) {
itemMeta.addEnchant(enchantment, level, bypass);
return this;
}
public ItemBuilder shiny() {
return enchant(Enchantment.LURE, 1, true).flags(ItemFlag.values());
}
public ItemBuilder color(Color color) {
if (itemMeta instanceof LeatherArmorMeta) {
((LeatherArmorMeta) itemMeta).setColor(color);
}
return this;
}
public ItemBuilder banner(Pattern... patterns) {
if (itemMeta instanceof BannerMeta) {
java.util.Arrays.stream(patterns).forEach(pattern -> ((BannerMeta) itemMeta).addPattern(pattern));
}
return this;
}
public ItemBuilder potionData(PotionData potionData) {
if (itemMeta instanceof PotionMeta) {
((PotionMeta) itemMeta).setBasePotionData(potionData);
}
return this;
}
public ItemBuilder potionColor(Color color) {
if (itemMeta instanceof PotionMeta) {
((PotionMeta) itemMeta).setColor(color);
}
return this;
}
public ItemBuilder potionEffect(PotionEffect potionEffect) {
if (itemMeta instanceof PotionMeta) {
((PotionMeta) itemMeta).addCustomEffect(potionEffect, false);
}
return this;
}
public ItemBuilder potionEffect(PotionEffect potionEffect, boolean b) {
if (itemMeta instanceof PotionMeta) {
((PotionMeta) itemMeta).addCustomEffect(potionEffect, b);
}
return this;
}
public ItemBuilder eggType(EntityType entityType) {
if (itemMeta instanceof SpawnEggMeta) {
((SpawnEggMeta) itemMeta).setSpawnedType(entityType);
}
return this;
}
public ItemBuilder skullOwner(String name) {
if (itemMeta instanceof SkullMeta) {
((SkullMeta) itemMeta).setOwner(name);
}
return this;
}
public ItemBuilder unbreakable(boolean value) {
if (Version.isAfter(Version.v1_12)) {
itemMeta.setUnbreakable(value);
} else {
itemMeta.spigot().setUnbreakable(value);
}
return this;
}
public ItemBuilder colored() {
if (itemMeta.hasDisplayName()) {
itemMeta.setDisplayName(TLocale.Translate.setColored(itemMeta.getDisplayName()));
}
if (itemMeta.hasLore()) {
itemMeta.setLore(TLocale.Translate.setColored(itemMeta.getLore()));
}
return this;
}
public ItemStack build() {
ItemStack buildItem = itemStack.clone();
if (itemMeta != null) {
buildItem.setItemMeta(itemMeta.clone());
}
return buildItem;
}
}

View File

@@ -0,0 +1,286 @@
package io.izzel.taboolib.module.item;
import io.izzel.taboolib.Version;
import io.izzel.taboolib.locale.TLocale;
import io.izzel.taboolib.module.lite.SimpleI18n;
import io.izzel.taboolib.module.nms.NMSHandler;
import io.izzel.taboolib.module.nms.nbt.NBTBase;
import io.izzel.taboolib.module.nms.nbt.NBTCompound;
import io.izzel.taboolib.module.nms.nbt.NBTList;
import io.izzel.taboolib.origin.lite.Numbers;
import org.bukkit.Color;
import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.inventory.meta.LeatherArmorMeta;
import org.bukkit.inventory.meta.PotionMeta;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.util.NumberConversions;
import java.util.List;
/**
* @Author 坏黑
* @Since 2019-07-05 16:44
*/
public class Items {
public final static Integer[] INVENTORY_CENTER = {
10, 11, 12, 13, 14, 15, 16,
19, 20, 21, 22, 23, 24, 25,
28, 29, 30, 31, 32, 33, 34,
37, 38, 39, 40, 41, 42, 43
};
public static String getName(ItemStack item) {
return SimpleI18n.getCustomName(item);
}
public static boolean isNull(ItemStack item) {
return item == null || item.getType().equals(Material.AIR);
}
public static boolean hasLore(ItemStack i, String a) {
return hasLore(i) && i.getItemMeta().getLore().toString().contains(a);
}
public static boolean hasLore(ItemStack i) {
return !isNull(i) && i.getItemMeta().hasLore();
}
public static boolean hasName(ItemStack i) {
return !isNull(i) && i.getItemMeta().hasDisplayName();
}
public static Material asMaterial(String args) {
try {
Material material = Material.getMaterial(args.toUpperCase());
return material != null ? material : Material.getMaterial(Integer.valueOf(args));
} catch (Exception e) {
return Material.STONE;
}
}
public static Enchantment asEnchantment(String enchant) {
try {
Enchantment enchantment = Enchantment.getByName(enchant);
return enchantment != null ? enchantment : Enchantment.getById(Integer.valueOf(enchant));
} catch (Exception e) {
return null;
}
}
public static PotionEffectType asPotionEffectType(String potion) {
try {
PotionEffectType type = PotionEffectType.getByName(potion);
return type != null ? type : PotionEffectType.getById(Integer.valueOf(potion));
} catch (Exception e) {
return null;
}
}
public static ItemFlag asItemFlag(String flag) {
try {
return ItemFlag.valueOf(flag);
} catch (Exception e) {
return null;
}
}
public static Color asColor(String color) {
try {
return Color.fromBGR(Integer.valueOf(color.split("-")[0]), Integer.valueOf(color.split("-")[1]), Integer.valueOf(color.split("-")[2]));
} catch (Exception e) {
return Color.fromBGR(0, 0, 0);
}
}
public static String asAttribute(String name) {
switch (name.toLowerCase()) {
case "damage":
return "generic.attackDamage";
case "attackspeed":
return "generic.attackSpeed";
case "health":
return "generic.maxHealth";
case "speed":
return "generic.movementSpeed";
case "knockback":
return "generic.knockbackResistance";
case "armor":
return "generic.armor";
case "luck":
return "generic.luck";
default:
return null;
}
}
public static ItemStack replaceLore(ItemStack item, String loreOld, String loreNew) {
if (hasLore(item)) {
ItemMeta meta = item.getItemMeta();
List<String> lore = meta.getLore();
for (int i = 0; i < lore.size(); i++) {
lore.set(i, lore.get(i).replace(loreOld, loreNew));
}
meta.setLore(lore);
item.setItemMeta(meta);
}
return item;
}
public static boolean checkItem(Player player, ItemStack item, int amount, boolean remove) {
return checkItem(player.getInventory(), item, amount, remove);
}
public static boolean checkItem(Inventory inventory, ItemStack item, int amount, boolean remove) {
int hasAmount = 0;
for (ItemStack _item : inventory) {
if (item.isSimilar(_item)) {
hasAmount += _item.getAmount();
}
}
if (hasAmount < amount) {
return false;
}
int requireAmount = amount;
for (int i = 0; i < inventory.getSize() && remove; i++) {
ItemStack _item = inventory.getItem(i);
if (_item != null && _item.isSimilar(item)) {
if (_item.getAmount() < requireAmount) {
inventory.setItem(i, null);
requireAmount -= _item.getAmount();
} else if (_item.getAmount() == requireAmount) {
inventory.setItem(i, null);
return true;
} else {
_item.setAmount(_item.getAmount() - requireAmount);
return true;
}
}
}
return true;
}
public static ItemStack loadItem(ConfigurationSection section) {
if (section.get("bukkit") instanceof ItemStack) {
return section.getItemStack("bukkit");
}
// 材质
ItemStack item = new ItemStack(asMaterial(section.getString("material")));
// 数量
item.setAmount(section.contains("amount") ? section.getInt("amount") : 1);
// 耐久
item.setDurability((short) section.getInt("data"));
// 元数据
ItemMeta meta = item.getItemMeta();
// 展示名
if (section.contains("name")) {
meta.setDisplayName(section.getString("name"));
}
// 描述
if (section.contains("lore")) {
meta.setLore(section.getStringList("lore"));
}
// 附魔
if (section.contains("enchant")) {
for (String preEnchant : section.getConfigurationSection("enchant").getKeys(false)) {
Enchantment enchant = asEnchantment(preEnchant);
if (enchant != null) {
meta.addEnchant(enchant, section.getInt("enchant." + preEnchant), true);
} else {
TLocale.Logger.error("ITEM-UTILS.FAIL-LOAD-ENCHANTS", preEnchant);
}
}
}
// 标签
if (section.contains("flags") && Version.isAfter(Version.v1_8)) {
for (String preFlag : section.getStringList("flags")) {
ItemFlag flag = asItemFlag(preFlag);
if (flag != null) {
meta.addItemFlags(flag);
} else {
TLocale.Logger.error("ITEM-UTILS.FAIL-LOAD-FLAG", preFlag);
}
}
}
// 皮革
if (meta instanceof LeatherArmorMeta && section.contains("color")) {
((LeatherArmorMeta) meta).setColor(asColor(section.getString("color")));
}
// 药水
if (meta instanceof PotionMeta && section.contains("potions")) {
PotionMeta potionMeta = (PotionMeta) meta;
for (String prePotionName : section.getConfigurationSection("potions").getKeys(false)) {
PotionEffectType potionEffectType = asPotionEffectType(prePotionName);
if (potionEffectType != null) {
potionMeta.addCustomEffect(new PotionEffect(
potionEffectType,
NumberConversions.toInt(section.getString("potions." + prePotionName).split("-")[0]),
NumberConversions.toInt(section.getString("potions." + prePotionName).split("-")[1]) - 1), true);
} else {
TLocale.Logger.error("ITEM-UTILS.FAIL-LOAD-POTION", prePotionName);
}
}
}
// 元数据
item.setItemMeta(meta);
// 数据
NBTCompound nbt = NMSHandler.getHandler().loadNBT(item);
// 物品标签
if (section.contains("nbt")) {
for (String name : section.getConfigurationSection("nbt").getKeys(false)) {
Object obj = section.get("nbt." + name);
if (obj instanceof String) {
nbt.put(name, new NBTBase(obj.toString()));
} else if (obj instanceof Double) {
nbt.put(name, new NBTBase(NumberConversions.toDouble(obj)));
} else if (obj instanceof Integer) {
nbt.put(name, new NBTBase(NumberConversions.toInt(obj)));
} else if (obj instanceof Long) {
nbt.put(name, new NBTBase(NumberConversions.toLong(obj)));
}
}
}
// 物品属性
if (section.contains("attributes")) {
NBTList attr = new NBTList();
for (String hand : section.getConfigurationSection("attributes").getKeys(false)) {
for (String name : section.getConfigurationSection("attributes." + hand).getKeys(false)) {
if (asAttribute(name) != null) {
try {
NBTCompound a = new NBTCompound();
String num = section.getString("attributes." + hand + "." + name);
if (num.endsWith("%")) {
a.put("Amount", new NBTBase(NumberConversions.toDouble(num.substring(0, num.length() - 1)) / 100D));
a.put("Operation", new NBTBase(1));
} else {
a.put("Amount", new NBTBase(NumberConversions.toDouble(num)));
a.put("Operation", new NBTBase(0));
}
a.put("AttributeName", new NBTBase(asAttribute(name)));
a.put("UUIDMost", new NBTBase(Numbers.getRandom().nextInt(Integer.MAX_VALUE)));
a.put("UUIDLeast", new NBTBase(Numbers.getRandom().nextInt(Integer.MAX_VALUE)));
a.put("Name", new NBTBase(asAttribute(name)));
if (!hand.equals("all")) {
a.put("Slot", new NBTBase(hand));
}
attr.add(a);
} catch (Exception ignored) {
}
} else {
TLocale.Logger.error("ITEM-UTILS.FAIL-LOAD-POTION", name);
}
}
}
nbt.put("AttributeModifiers", attr);
}
return NMSHandler.getHandler().saveNBT(item, nbt);
}
}

View File

@@ -0,0 +1,44 @@
package io.izzel.taboolib.module.item.inventory;
import org.bukkit.entity.Player;
import org.bukkit.event.Event;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryDragEvent;
import org.bukkit.event.inventory.InventoryInteractEvent;
/**
* @Author 坏黑
* @Since 2019-05-21 18:09
*/
public class ClickEvent {
private ClickType clickType;
private Event event;
private char slot;
public ClickEvent(ClickType clickType, Event event, char slot) {
this.clickType = clickType;
this.event = event;
this.slot = slot;
}
public InventoryClickEvent castClick() {
return (InventoryClickEvent) event;
}
public InventoryDragEvent castDrag() {
return (InventoryDragEvent) event;
}
public char getSlot() {
return slot;
}
public ClickType getClickType() {
return clickType;
}
public Player getClicker() {
return (Player) ((InventoryInteractEvent) event).getWhoClicked();
}
}

View File

@@ -0,0 +1,66 @@
package io.izzel.taboolib.module.item.inventory;
import io.izzel.taboolib.module.inject.TListener;
import org.bukkit.Bukkit;
import org.bukkit.entity.HumanEntity;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.event.inventory.InventoryDragEvent;
import org.bukkit.event.player.PlayerDropItemEvent;
import org.bukkit.event.player.PlayerItemHeldEvent;
import org.bukkit.event.server.PluginDisableEvent;
import java.util.Optional;
/**
* @Author 坏黑
* @Since 2019-05-21 18:16
*/
@TListener
class ClickListener implements Listener {
@EventHandler
public void onDisable(PluginDisableEvent e) {
Bukkit.getOnlinePlayers().stream().filter(player -> player.getOpenInventory().getTopInventory().getHolder() instanceof MenuHolder && e.getPlugin().equals(((MenuHolder) player.getOpenInventory().getTopInventory().getHolder()).getBuilder().getPlugin())).forEach(HumanEntity::closeInventory);
}
@EventHandler
public void onClick(InventoryClickEvent e) {
if (e.getInventory().getHolder() instanceof MenuHolder) {
if (((MenuHolder) e.getInventory().getHolder()).getBuilder().isLockHand() && (e.getRawSlot() - e.getInventory().getSize() - 27 == e.getWhoClicked().getInventory().getHeldItemSlot() || (e.getClick() == org.bukkit.event.inventory.ClickType.NUMBER_KEY && e.getHotbarButton() == e.getWhoClicked().getInventory().getHeldItemSlot()))) {
e.setCancelled(true);
}
Optional.ofNullable(((MenuHolder) e.getInventory().getHolder()).getBuilder().getClickTask()).ifPresent(t -> t.run(new ClickEvent(ClickType.CLICK, e, ((MenuHolder) e.getInventory().getHolder()).getBuilder().getSlot(e.getRawSlot()))));
}
}
@EventHandler
public void onDrag(InventoryDragEvent e) {
if (e.getInventory().getHolder() instanceof MenuHolder) {
Optional.ofNullable(((MenuHolder) e.getInventory().getHolder()).getBuilder().getClickTask()).ifPresent(t -> t.run(new ClickEvent(ClickType.DRAG, e, ' ')));
}
}
@EventHandler
public void onDrag(InventoryCloseEvent e) {
if (e.getInventory().getHolder() instanceof MenuHolder) {
Optional.ofNullable(((MenuHolder) e.getInventory().getHolder()).getBuilder().getCloseTask()).ifPresent(t -> t.run(e));
}
}
@EventHandler
public void onDrop(PlayerDropItemEvent e) {
if (e.getPlayer().getOpenInventory().getTopInventory().getHolder() instanceof MenuHolder && ((MenuHolder) e.getPlayer().getOpenInventory().getTopInventory().getHolder()).getBuilder().isLockHand()) {
e.setCancelled(true);
}
}
@EventHandler
public void onHeld(PlayerItemHeldEvent e) {
if (e.getPlayer().getOpenInventory().getTopInventory().getHolder() instanceof MenuHolder && ((MenuHolder) e.getPlayer().getOpenInventory().getTopInventory().getHolder()).getBuilder().isLockHand()) {
e.setCancelled(true);
}
}
}

View File

@@ -0,0 +1,22 @@
package io.izzel.taboolib.module.item.inventory;
import io.izzel.taboolib.module.inject.TListener;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerSwapHandItemsEvent;
/**
* @Author 坏黑
* @Since 2019-05-21 22:04
*/
@TListener(version = ">=10900")
class ClickListenerOffhand implements Listener {
@EventHandler
public void onSwap(PlayerSwapHandItemsEvent e) {
if (e.getPlayer().getOpenInventory().getTopInventory().getHolder() instanceof MenuHolder && ((MenuHolder) e.getPlayer().getOpenInventory().getTopInventory().getHolder()).getBuilder().isLockHand()) {
e.setCancelled(true);
}
}
}

View File

@@ -0,0 +1,11 @@
package io.izzel.taboolib.module.item.inventory;
/**
* @Author 坏黑
* @Since 2019-05-21 18:14
*/
public interface ClickTask {
void run(ClickEvent event);
}

View File

@@ -0,0 +1,11 @@
package io.izzel.taboolib.module.item.inventory;
/**
* @Author 坏黑
* @Since 2019-05-21 18:10
*/
public enum ClickType {
CLICK, DRAG
}

View File

@@ -0,0 +1,13 @@
package io.izzel.taboolib.module.item.inventory;
import org.bukkit.event.inventory.InventoryCloseEvent;
/**
* @Author 坏黑
* @Since 2019-05-21 18:14
*/
public interface CloseTask {
void run(InventoryCloseEvent event);
}

View File

@@ -0,0 +1,139 @@
package io.izzel.taboolib.module.item.inventory;
import com.google.common.collect.Maps;
import io.izzel.taboolib.TabooLib;
import io.izzel.taboolib.util.Ref;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.Plugin;
import java.util.Map;
/**
* @Author 坏黑
* @Since 2019-05-21 15:54
*/
public class MenuBuilder {
private Map<Character, ItemStack> keys = Maps.newHashMap();
private Plugin plugin;
private String title;
private int rows;
private char[][] items ;
private ClickTask clickTask;
private CloseTask closeTask;
private boolean lockHand;
public MenuBuilder(Plugin plugin) {
this.plugin = plugin;
}
public static MenuBuilder builder(Plugin plugin) {
return new MenuBuilder(plugin);
}
public static MenuBuilder builder() {
return new MenuBuilder(Ref.getCallerPlugin(Ref.getCallerClass(3).orElse(TabooLib.class)));
}
public MenuBuilder lockHand() {
this.lockHand = true;
return this;
}
public MenuBuilder event(ClickTask clickTask) {
this.clickTask = clickTask;
return this;
}
public MenuBuilder close(CloseTask closeTask) {
this.closeTask = closeTask;
return this;
}
public MenuBuilder title(String title) {
this.title = title;
return this;
}
public MenuBuilder rows(int rows) {
this.rows = rows * 9;
return this;
}
public MenuBuilder put(char key, ItemStack item) {
keys.put(key, item);
return this;
}
public MenuBuilder items(String... placeholder) {
items = new char[placeholder.length][];
for (int i = 0; i < placeholder.length; i++) {
items[i] = placeholder[i].toCharArray();
}
return this;
}
public Inventory build() {
Inventory inventory = Bukkit.createInventory(new MenuHolder(this), rows, String.valueOf(title));
for (int i = 0; i < items.length && i < rows; i++) {
char[] line = items[i];
for (int j = 0; j < line.length && j < 9; j++) {
inventory.setItem(i * 9 + j, keys.getOrDefault(line[j], new ItemStack(Material.AIR)));
}
}
return inventory;
}
public char getSlot(int slot) {
for (int i = 0; i < items.length && i < rows; i++) {
char[] line = items[i];
for (int j = 0; j < line.length && j < 9; j++) {
if (i * 9 + j == slot) {
return line[j];
}
}
}
return ' ';
}
// *********************************
//
// Getter and Setter
//
// *********************************
public Map<Character, ItemStack> getKeys() {
return keys;
}
public Plugin getPlugin() {
return plugin;
}
public String getTitle() {
return title;
}
public int getRows() {
return rows;
}
public char[][] getItems() {
return items;
}
public ClickTask getClickTask() {
return clickTask;
}
public CloseTask getCloseTask() {
return closeTask;
}
public boolean isLockHand() {
return lockHand;
}
}

View File

@@ -0,0 +1,26 @@
package io.izzel.taboolib.module.item.inventory;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;
/**
* @Author 坏黑
* @Since 2019-05-21 20:28
*/
class MenuHolder implements InventoryHolder {
private MenuBuilder builder;
public MenuHolder(MenuBuilder builder) {
this.builder = builder;
}
public MenuBuilder getBuilder() {
return builder;
}
@Override
public Inventory getInventory() {
return null;
}
}

View File

@@ -0,0 +1,61 @@
package io.izzel.taboolib.module.lite;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import java.util.stream.IntStream;
/**
* 我不信 ClassNotFoundException 的邪,自己写了一个发现还是一样。。。
*
* @Author sky
* @Since 2018-09-19 21:17
*/
public class SimpleClassVisitor extends ClassVisitor {
private final SimpleVersionControl simpleVersionControl;
public SimpleClassVisitor(SimpleVersionControl simpleVersionControl, ClassVisitor classVisitor) {
super(Opcodes.ASM5, classVisitor);
this.simpleVersionControl = simpleVersionControl;
}
@Override
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
super.visit(version, access, translate(name), translate(signature), translate(superName), translate(interfaces));
}
@Override
public void visitInnerClass(String name, String outerName, String innerName, int access) {
super.visitInnerClass(translate(name), translate(outerName), translate(innerName), access);
}
@Override
public FieldVisitor visitField(int access, String name, String descriptor, String signature, Object value) {
return super.visitField(access, translate(name), translate(descriptor), translate(signature), value instanceof String ? translate((String) value) : value);
}
@Override
public void visitOuterClass(String owner, String name, String descriptor) {
super.visitOuterClass(translate(owner), translate(name), translate(descriptor));
}
@Override
public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
return new SimpleMethodVisitor(simpleVersionControl, super.visitMethod(access, translate(name), translate(descriptor), translate(signature), translate(exceptions)));
}
private String translate(String target) {
return target == null ? null : simpleVersionControl.replace(target);
}
private String[] translate(String[] target) {
if (target == null) {
return target;
}
IntStream.range(0, target.length).forEach(i -> target[i] = translate(target[i]));
return target;
}
}

View File

@@ -0,0 +1,40 @@
package io.izzel.taboolib.module.lite;
/**
* @Author sky
* @Since 2018-09-25 15:21
*/
public class SimpleCounter {
private int timer;
private int limit;
private boolean ignoredFirst;
private boolean counterFirst;
public SimpleCounter(int limit) {
this(limit, false);
}
public SimpleCounter(int limit, boolean ignoredFirst) {
this.timer = 0;
this.limit = limit;
this.ignoredFirst = ignoredFirst;
this.counterFirst = true;
}
public boolean next() {
if (--timer <= 0) {
timer = limit;
if (ignoredFirst && counterFirst) {
counterFirst = false;
} else {
return true;
}
}
return false;
}
public void reset() {
timer = 0;
}
}

View File

@@ -0,0 +1,78 @@
package io.izzel.taboolib.module.lite;
import com.google.common.collect.Maps;
import org.bukkit.entity.Player;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack;
import java.util.Arrays;
import java.util.Map;
/**
* @Author 坏黑
* @Since 2019-04-25 22:01
*/
public enum SimpleEquip {
HAND(EquipmentSlot.HAND, -1),
OFF_HAND(EquipmentSlot.OFF_HAND, 40),
FEET(EquipmentSlot.FEET, 36),
LEGS(EquipmentSlot.LEGS, 37),
CHEST(EquipmentSlot.CHEST, 38),
HEAD(EquipmentSlot.HEAD, 39);
private EquipmentSlot bukkit;
private int slot;
SimpleEquip(EquipmentSlot bukkit, int slot) {
this.bukkit = bukkit;
this.slot = slot;
}
public void setItem(Player player, ItemStack item) {
if (this != HAND) {
player.getInventory().setItem(slot, item);
} else {
player.setItemInHand(item);
}
}
public ItemStack getItem(Player player) {
if (this != HAND) {
return player.getInventory().getItem(slot);
} else {
return player.getItemInHand();
}
}
public static SimpleEquip fromBukkit(EquipmentSlot bukkit) {
return Arrays.stream(values()).filter(tEquipment -> tEquipment.bukkit == bukkit).findFirst().orElse(null);
}
public static Map<SimpleEquip, ItemStack> getItems(Player player) {
Map<SimpleEquip, ItemStack> map = Maps.newHashMap();
for (SimpleEquip equipment : values()) {
map.put(equipment, equipment.getItem(player));
}
return map;
}
// *********************************
//
// Getter and Setter
//
// *********************************
public EquipmentSlot getBukkit() {
return bukkit;
}
public int getSlot() {
return slot;
}
}

View File

@@ -0,0 +1,101 @@
package io.izzel.taboolib.module.lite;
import io.izzel.taboolib.TabooLib;
import io.izzel.taboolib.Version;
import io.izzel.taboolib.locale.TLocaleLoader;
import io.izzel.taboolib.module.inject.TFunction;
import io.izzel.taboolib.module.nms.NMSHandler;
import io.izzel.taboolib.module.nms.nbt.NBTCompound;
import io.izzel.taboolib.util.Files;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Entity;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.BookMeta;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.inventory.meta.SpawnEggMeta;
import org.bukkit.plugin.Plugin;
import java.io.File;
import java.util.Optional;
/**
* @Author 坏黑
* @Since 2019-05-22 1:16
*/
@TFunction(enable = "init")
public class SimpleI18n {
private static FileConfiguration lang;
private static boolean released;
static void init() {
File localeFile = getLocaleFile(TabooLib.getPlugin());
if (localeFile == null) {
lang = new YamlConfiguration();
} else {
lang = Files.load(TabooLib.getPlugin(), localeFile);
}
if (lang.getInt("version") < 3 && !released) {
released = true;
Files.deepDelete(new File(TabooLib.getPlugin().getDataFolder(), "simpleI18n"));
init();
}
}
public static String getCustomName(Entity entity) {
return entity != null ? Optional.ofNullable(entity.getCustomName()).orElse(getName(entity)) : getName(entity);
}
public static String getCustomName(ItemStack item) {
if (item != null) {
ItemMeta itemMeta = item.getItemMeta();
return itemMeta != null && itemMeta.hasDisplayName() ? itemMeta.getDisplayName() : getName(item);
}
return getName(item);
}
public static String getName(Entity entity) {
return entity == null ? "-" : lang.getString(NMSHandler.getHandler().getName(entity).replace(".", "_"), entity.getName());
}
public static String getName(ItemStack item) {
if (item == null) {
return "-";
}
ItemMeta itemMeta = item.getItemMeta();
if (itemMeta instanceof BookMeta && ((BookMeta) itemMeta).getTitle() != null) {
return ((BookMeta) itemMeta).getTitle();
}
if (!Version.isAfter(Version.v1_11)) {
if (item.getType().name().equals("MONSTER_EGG")) {
NBTCompound nbtCompound = NMSHandler.getHandler().loadNBT(item);
if (nbtCompound.containsKey("EntityTag")) {
return lang.getString("item_monsterPlacer_name") + " " + lang.getString("entity_" + nbtCompound.get("EntityTag").asCompound().get("id").asString() + "_name");
}
return lang.getString("item_monsterPlacer_name");
}
} else if (!Version.isAfter(Version.v1_13)) {
if (itemMeta instanceof SpawnEggMeta) {
String spawnEggType = lang.getString("entity_" + ((SpawnEggMeta) itemMeta).getSpawnedType().getEntityClass().getSimpleName().replace(".", "_") + "_name");
if (spawnEggType != null) {
return lang.getString(NMSHandler.getHandler().getName(item).replace(".", "_"), item.getType().name().toLowerCase().replace("_", "")) + " " + spawnEggType;
}
}
}
return lang.getString(NMSHandler.getHandler().getName(item).replace(".", "_"), item.getType().name().toLowerCase().replace("_", ""));
}
private static void releaseLocales(Plugin plugin) {
TLocaleLoader.getLocalePriority().stream().filter(localeName -> !new File("plugins/TabooLib/simpleI18n/" + getVersion() + "/" + localeName + ".yml").exists() && plugin.getResource("simpleI18n/" + getVersion() + "/" + localeName + ".yml") != null).forEach(localeName -> plugin.saveResource("simpleI18n/" + getVersion() + "/" + localeName + ".yml", true));
}
private static File getLocaleFile(Plugin plugin) {
releaseLocales(plugin);
return TLocaleLoader.getLocalePriority().stream().map(localeName -> new File("plugins/TabooLib/simpleI18n/" + getVersion() + "/" + localeName + ".yml")).filter(File::exists).findFirst().orElse(null);
}
private static String getVersion() {
return Version.isAfter(Version.v1_13) ? "high" : "low";
}
}

View File

@@ -0,0 +1,51 @@
package io.izzel.taboolib.module.lite;
import com.google.common.collect.Lists;
import java.util.List;
import java.util.Map;
/**
* @Author sky
* @Since 2018-10-01 16:19
*/
public class SimpleIterator {
private final Object container;
public SimpleIterator(Object container) {
this.container = container;
}
public List<Map.Entry> mapIterator(int start, int end) {
List<Map.Entry> iterator = Lists.newArrayList();
Map container = (Map) this.container;
int loop = 0;
for (Object entry : container.entrySet()) {
if (loop++ >= start) {
if (loop <= end) {
iterator.add((Map.Entry) entry);
} else {
break;
}
}
}
return iterator;
}
public List listIterator(int start, int end) {
List iterator = Lists.newArrayList();
List container = (List) this.container;
int loop = 0;
for (Object entry : container) {
if (loop++ >= start) {
if (loop <= end) {
iterator.add(entry);
} else {
break;
}
}
}
return iterator;
}
}

View File

@@ -0,0 +1,77 @@
package io.izzel.taboolib.module.lite;
import org.objectweb.asm.*;
import java.util.stream.IntStream;
/**
* 我不信 ClassNotFound 的邪,自己写了一个发现还是一样。。。
*
* @Author sky
* @Since 2018-9-19 21:33
*/
public class SimpleMethodVisitor extends MethodVisitor {
private final SimpleVersionControl simpleVersionControl;
public SimpleMethodVisitor(SimpleVersionControl simpleVersionControl, MethodVisitor methodVisitor) {
super(Opcodes.ASM5, methodVisitor);
this.simpleVersionControl = simpleVersionControl;
}
@Override
public void visitParameter(String name, int access) {
super.visitParameter(translate(name), access);
}
@Override
public void visitMethodInsn(int opcode, String owner, String name, String descriptor) {
super.visitMethodInsn(opcode, translate(owner), translate(name), translate(descriptor));
}
@Override
public void visitMethodInsn(int opcode, String owner, String name, String descriptor, boolean isInterface) {
super.visitMethodInsn(opcode, translate(owner), translate(name), translate(descriptor), isInterface);
}
@Override
public void visitLdcInsn(Object value) {
if (value instanceof Type) {
super.visitLdcInsn(Type.getType(translate(((Type) value).getDescriptor())));
} else {
super.visitLdcInsn(value);
}
}
@Override
public void visitTypeInsn(int opcode, String type) {
super.visitTypeInsn(opcode, translate(type));
}
@Override
public void visitFieldInsn(int opcode, String owner, String name, String descriptor) {
super.visitFieldInsn(opcode, translate(owner), translate(name), translate(descriptor));
}
@Override
public void visitLocalVariable(String name, String descriptor, String signature, Label start, Label end, int index) {
super.visitLocalVariable(translate(name), translate(descriptor), translate(signature), start, end, index);
}
@Override
public void visitInvokeDynamicInsn(String name, String descriptor, Handle bootstrapMethodHandle, Object... bootstrapMethodArguments) {
super.visitInvokeDynamicInsn(translate(name), translate(descriptor), bootstrapMethodHandle, bootstrapMethodArguments);
}
private String translate(String target) {
return target == null ? null : simpleVersionControl.replace(target);
}
private String[] translate(String[] target) {
if (target == null) {
return target;
}
IntStream.range(0, target.length).forEach(i -> target[i] = translate(target[i]));
return target;
}
}

View File

@@ -0,0 +1,133 @@
package io.izzel.taboolib.module.lite;
import com.google.common.collect.Maps;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.Map;
/**
* @Author 坏黑
* @Since 2018-10-25 22:51
*/
public class SimpleReflection {
private static Map<String, Map<String, Field>> fieldCached = Maps.newHashMap();
public static boolean isExists(Class<?> nmsClass) {
return fieldCached.containsKey(nmsClass.getName());
}
public static Map<String, Field> getFields(Class<?> nmsClass) {
return fieldCached.getOrDefault(nmsClass.getName(), Maps.newHashMap());
}
public static Field getField(Class<?> nmsClass, String fieldName) {
return fieldCached.getOrDefault(nmsClass.getName(), Maps.newHashMap()).get(fieldName);
}
public static void checkAndSave(Class<?> nmsClass) {
if (!isExists(nmsClass)) {
saveField(nmsClass);
}
}
public static void saveField(Class<?> nmsClass) {
try {
Arrays.stream(nmsClass.getDeclaredFields()).forEach(declaredField -> saveField(nmsClass, declaredField.getName()));
} catch (Exception e) {
e.printStackTrace();
}
}
public static void saveField(Class<?> nmsClass, String fieldName) {
try {
Field declaredField = nmsClass.getDeclaredField(fieldName);
declaredField.setAccessible(true);
fieldCached.computeIfAbsent(nmsClass.getName(), name -> Maps.newHashMap()).put(fieldName, declaredField);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void setFieldValue(Class<?> nmsClass, Object instance, String fieldName, Object value) {
try {
Map<String, Field> fields = fieldCached.get(nmsClass.getName());
if (fields == null) {
return;
}
Field field = fields.get(fieldName);
if (value == null) {
return;
}
field.set(instance, value);
} catch (Exception e) {
e.printStackTrace();
}
}
public static Object getFieldValue(Class<?> nmsClass, Object instance, String fieldName) {
try {
Map<String, Field> fields = fieldCached.get(nmsClass.getName());
if (fields == null) {
return null;
}
Field field = fields.get(fieldName);
if (field == null) {
return null;
}
return field.get(instance);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static <T> T getFieldValue(Class<?> nmsClass, Object instance, String fieldName, T def) {
try {
Map<String, Field> fields = fieldCached.get(nmsClass.getName());
if (fields == null) {
return def;
}
Field field = fields.get(fieldName);
if (field == null) {
return def;
}
return (T) field.get(instance);
} catch (Exception e) {
e.printStackTrace();
}
return def;
}
public static Class getListType(Field field) {
Type genericType = field.getGenericType();
try {
if (ParameterizedType.class.isAssignableFrom(genericType.getClass())) {
for (Type actualTypeArgument : ((ParameterizedType) genericType).getActualTypeArguments()) {
return Class.forName(actualTypeArgument.getTypeName());
}
}
} catch (Throwable t) {
t.printStackTrace();
}
return null;
}
public static Class[] getMapType(Field field) {
Class[] mapType = new Class[2];
try {
Type genericType = field.getGenericType();
if (ParameterizedType.class.isAssignableFrom(genericType.getClass())) {
for (Type actualTypeArgument : ((ParameterizedType) genericType).getActualTypeArguments()) {
mapType[mapType[0] == null ? 0 : 1] = Class.forName(actualTypeArgument.getTypeName());
}
}
} catch (Throwable t) {
t.printStackTrace();
}
return mapType[1] == null ? null : mapType ;
}
}

View File

@@ -0,0 +1,156 @@
package io.izzel.taboolib.module.lite;
import com.google.common.collect.Lists;
import io.izzel.taboolib.TabooLib;
import io.izzel.taboolib.Version;
import io.izzel.taboolib.util.Files;
import io.izzel.taboolib.util.asm.AsmClassLoader;
import org.bukkit.plugin.Plugin;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @Author sky
* @Since 2018-09-19 21:05
*/
public class SimpleVersionControl {
private static Map<String, Class<?>> cacheClasses = new HashMap<>();
private String target;
private String to;
private List<String> from = Lists.newArrayList();
private Plugin plugin;
private boolean useCache;
private boolean useNMS;
SimpleVersionControl() {
useCache = false;
}
public static SimpleVersionControl create() {
return new SimpleVersionControl().to(Version.getBukkitVersion()).plugin(TabooLib.getPlugin());
}
public static SimpleVersionControl create(String toVersion) {
return new SimpleVersionControl().to(toVersion).plugin(TabooLib.getPlugin());
}
public static SimpleVersionControl createSimple(String target, String... from) {
return create().target(target).from(from);
}
public static SimpleVersionControl createNMS(String target) {
return create().target(target).useNMS();
}
/**
* 设置转换类地址写法如me.skymc.taboolib.packet.InternalPacket
*/
public SimpleVersionControl target(String target) {
this.target = target;
return this;
}
/**
* 设置原版本写法如v1_8_R3
*/
public SimpleVersionControl from(String from) {
this.from.add(from.startsWith("v") ? from : "v" + from);
return this;
}
/**
* 设置原版本写法如v1_8_R3, v1_12_R1
*/
public SimpleVersionControl from(String... from) {
Arrays.stream(from).forEach(v -> this.from.add(v.startsWith("v") ? v : "v" + v));
return this;
}
/**
* 设置目标版本
*/
public SimpleVersionControl to(String to) {
this.to = to.startsWith("v") ? to : "v" + to;
return this;
}
/**
* 设置插件,不填默认指向 TabooLib
*/
public SimpleVersionControl plugin(Plugin plugin) {
this.plugin = plugin;
return this;
}
/**
* 转换类将会保存在 TabooLib 中,防止出现 NoClassDefFoundError 异常
*/
public SimpleVersionControl useCache() {
this.useCache = true;
return this;
}
/**
* 自动转换所有使用到的 NMS 或 OBC 方法
*/
public SimpleVersionControl useNMS() {
this.useNMS = true;
return this;
}
public Class<?> translate() throws IOException {
return translate(plugin);
}
public Class<?> translate(Plugin plugin) throws IOException {
if (useCache && cacheClasses.containsKey(target)) {
return cacheClasses.get(target);
}
ClassReader classReader = new ClassReader(Files.getResource(plugin, target.replace(".", "/") + ".class"));
ClassWriter classWriter = new ClassWriter(0);
ClassVisitor classVisitor = new SimpleClassVisitor(this, classWriter);
classReader.accept(classVisitor, ClassReader.EXPAND_FRAMES);
classWriter.visitEnd();
classVisitor.visitEnd();
Class<?> newClass = AsmClassLoader.createNewClass(target, classWriter.toByteArray());
if (useCache) {
cacheClasses.put(target, newClass);
}
return newClass;
}
// *********************************
//
// Getter and Setter
//
// *********************************
public String getTarget() {
return target;
}
public List<String> getFrom() {
return from;
}
public String getTo() {
return to;
}
public String replace(String origin) {
if (useNMS) {
origin = origin.replaceAll("net/minecraft/server/.*?/", "net/minecraft/server/" + to + "/").replaceAll("org/bukkit/craftbukkit/.*?/", "org/bukkit/craftbukkit/" + to + "/");
}
for (String from : from) {
origin = origin.replace("/" + from + "/", "/" + to + "/");
}
return origin;
}
}

View File

@@ -0,0 +1,128 @@
package io.izzel.taboolib.module.logger;
import io.izzel.taboolib.TabooLibAPI;
import io.izzel.taboolib.locale.TLocale;
import io.izzel.taboolib.util.Strings;
import net.md_5.bungee.BungeeCord;
import net.md_5.bungee.api.chat.TextComponent;
import org.bukkit.Bukkit;
import org.bukkit.plugin.Plugin;
public class TLogger {
public static final int VERBOSE = 0, FINEST = 1, FINE = 2, INFO = 3, WARN = 4, ERROR = 5, FATAL = 6;
private final String pattern;
private final String name;
private int level;
public TLogger(String pattern, Plugin plugin, int level) {
this.pattern = pattern;
this.name = plugin.getName();
this.level = level;
}
public TLogger(String pattern, String name, int level) {
this.pattern = pattern;
this.name = name;
this.level = level;
}
public static TLogger getGlobalLogger() {
return io.izzel.taboolib.TabooLib.getLogger();
}
public static TLogger getUnformatted(Plugin plugin) {
return new TLogger("§8[§3§l{0}§8][§r{1}§8] §f{2}", plugin, TLogger.FINE);
}
public static TLogger getUnformatted(String name) {
return new TLogger("§8[§3§l{0}§8][§r{1}§8] §f{2}", name, TLogger.FINE);
}
public String getPattern() {
return pattern;
}
public String getName() {
return name;
}
public int getLevel() {
return level;
}
public void setLevel(int level) {
this.level = level;
}
public void verbose(String msg) {
if (level <= VERBOSE) {
if (TabooLibAPI.isBukkit()) {
Bukkit.getConsoleSender().sendMessage(Strings.replaceWithOrder(pattern, name, "§fVERBOSE", TLocale.Translate.setColored(msg)));
} else {
BungeeCord.getInstance().getConsole().sendMessage(TextComponent.fromLegacyText(Strings.replaceWithOrder(pattern, name, "§fVERBOSE", TLocale.Translate.setColored(msg))));
}
}
}
public void finest(String msg) {
if (level <= FINEST) {
if (TabooLibAPI.isBukkit()) {
Bukkit.getConsoleSender().sendMessage(Strings.replaceWithOrder(pattern, name, "§eFINEST", TLocale.Translate.setColored(msg)));
} else {
BungeeCord.getInstance().getConsole().sendMessage(TextComponent.fromLegacyText(Strings.replaceWithOrder(pattern, name, "§eFINEST", TLocale.Translate.setColored(msg))));
}
}
}
public void fine(String msg) {
if (level <= FINE) {
if (TabooLibAPI.isBukkit()) {
Bukkit.getConsoleSender().sendMessage(Strings.replaceWithOrder(pattern, name, "§aFINE", TLocale.Translate.setColored(msg)));
} else {
BungeeCord.getInstance().getConsole().sendMessage(TextComponent.fromLegacyText(Strings.replaceWithOrder(pattern, name, "§aFINE", TLocale.Translate.setColored(msg))));
}
}
}
public void info(String msg) {
if (level <= INFO) {
if (TabooLibAPI.isBukkit()) {
Bukkit.getConsoleSender().sendMessage(Strings.replaceWithOrder(pattern, name, "§bINFO", TLocale.Translate.setColored(msg)));
} else {
BungeeCord.getInstance().getConsole().sendMessage(TextComponent.fromLegacyText(Strings.replaceWithOrder(pattern, name, "§bINFO", TLocale.Translate.setColored(msg))));
}
}
}
public void warn(String msg) {
if (level <= WARN) {
if (TabooLibAPI.isBukkit()) {
Bukkit.getConsoleSender().sendMessage(Strings.replaceWithOrder(pattern, name, "§6WARN", "§6" + TLocale.Translate.setColored(msg)));
} else {
BungeeCord.getInstance().getConsole().sendMessage(TextComponent.fromLegacyText(Strings.replaceWithOrder(pattern, name, "§6WARN", "§6" + TLocale.Translate.setColored(msg))));
}
}
}
public void error(String msg) {
if (level <= ERROR) {
if (TabooLibAPI.isBukkit()) {
Bukkit.getConsoleSender().sendMessage(Strings.replaceWithOrder(pattern, name, "§cERROR", "§c" + TLocale.Translate.setColored(msg)));
} else {
BungeeCord.getInstance().getConsole().sendMessage(TextComponent.fromLegacyText(Strings.replaceWithOrder(pattern, name, "§cERROR", "§c" + TLocale.Translate.setColored(msg))));
}
}
}
public void fatal(String msg) {
if (level <= FATAL) {
if (TabooLibAPI.isBukkit()) {
Bukkit.getConsoleSender().sendMessage(Strings.replaceWithOrder(pattern, name, "§4FATAL", "§4" + TLocale.Translate.setColored(msg)));
} else {
BungeeCord.getInstance().getConsole().sendMessage(TextComponent.fromLegacyText(Strings.replaceWithOrder(pattern, name, "§4FATAL", "§4" + TLocale.Translate.setColored(msg))));
}
}
}
}

View File

@@ -0,0 +1,24 @@
package io.izzel.taboolib.module.logger;
import org.bukkit.plugin.Plugin;
import java.util.HashMap;
import java.util.Map;
public class TLoggerManager {
private static final Map<Plugin, TLogger> map = new HashMap<>();
public static void setDefaultLogger(Plugin plugin, TLogger logger) {
map.put(plugin, logger);
}
public static TLogger getLogger(Plugin plugin) {
TLogger logger = map.get(plugin);
if (logger == null) {
logger = TLogger.getUnformatted(plugin);
map.put(plugin, logger);
}
return logger;
}
}

View File

@@ -0,0 +1,11 @@
package io.izzel.taboolib.module.mysql;
/**
* @Author 坏黑
* @Since 2018-12-08 13:46
*/
public abstract class IColumn {
abstract public String convertToCommand();
}

View File

@@ -0,0 +1,42 @@
package io.izzel.taboolib.module.mysql;
import org.bukkit.plugin.Plugin;
/**
* @Author sky
* @Since 2018-05-14 19:07
*/
public abstract class IHost {
private Plugin plugin;
private boolean autoClose;
public IHost(Plugin plugin) {
this.plugin = plugin;
}
public IHost(Plugin plugin, boolean autoClose) {
this.plugin = plugin;
this.autoClose = autoClose;
}
public Plugin getPlugin() {
return plugin;
}
public void setPlugin(Plugin plugin) {
this.plugin = plugin;
}
public boolean isAutoClose() {
return autoClose;
}
public void setAutoClose(boolean autoClose) {
this.autoClose = autoClose;
}
abstract public String getConnectionUrl();
abstract public String getConnectionUrlSimple();
}

View File

@@ -0,0 +1,135 @@
package io.izzel.taboolib.module.mysql.builder;
import io.izzel.taboolib.util.Strings;
import io.izzel.taboolib.module.mysql.IColumn;
import java.util.Arrays;
/**
* @Author sky
* @Since 2018-05-14 19:09
*/
public class SQLColumn extends IColumn {
public static final SQLColumn PRIMARY_KEY_ID = new SQLColumn(SQLColumnType.INT, "id", SQLColumnOption.NOTNULL, SQLColumnOption.PRIMARY_KEY, SQLColumnOption.AUTO_INCREMENT);
private SQLColumnType columnType;
private int m;
private int d;
private String columnName;
private Object defaultValue;
private SQLColumnOption[] columnOptions;
/**
* 文本 类型常用构造器
* new SQLColumn(SQLColumnType.TEXT, "username");
*/
public SQLColumn(SQLColumnType columnType, String columnName) {
this(columnType, 0, 0, columnName, null);
}
/**
* CHAR 类型常用构造器
* new SQLColumn(SQLColumnType.CHAR, 1, "data");
*/
public SQLColumn(SQLColumnType columnType, int m, String columnName) {
this(columnType, m, 0, columnName, null);
}
/**
* 主键 类型常用构造器
* new SQLColumn(SQLColumnType.TEXT, "username", SQLColumnOption.PRIMARY_KEY, SQLColumnOption.AUTO_INCREMENT);
*/
public SQLColumn(SQLColumnType columnType, String columnName, SQLColumnOption... columnOptions) {
this(columnType, 0, 0, columnName, null, columnOptions);
}
/**
* 数据 类型常用构造器
* new SQLColumn(SQLColumnType.TEXT, "player_group", "PLAYER");
*/
public SQLColumn(SQLColumnType columnType, String columnName, Object defaultValue) {
this(columnType, 0, 0, columnName, defaultValue);
}
public SQLColumn(SQLColumnType columnType, String columnName, Object defaultValue, SQLColumnOption... columnOptions) {
this(columnType, 0, 0, columnName, defaultValue, columnOptions);
}
/**
* 完整构造器
*
* @param columnType 类型
* @param m m值
* @param d d值
* @param columnName 名称
* @param defaultValue 默认值
* @param columnOptions 属性值
*/
public SQLColumn(SQLColumnType columnType, int m, int d, String columnName, Object defaultValue, SQLColumnOption... columnOptions) {
this.columnType = columnType;
this.m = m;
this.d = d;
this.columnName = columnName;
this.defaultValue = defaultValue;
this.columnOptions = columnOptions;
}
public SQLColumn m(int m) {
this.m = m;
return this;
}
public SQLColumn d(int d) {
this.d = d;
return this;
}
public SQLColumn defaultValue(Object defaultValue) {
this.defaultValue = defaultValue;
return this;
}
public SQLColumn columnOptions(SQLColumnOption... columnOptions) {
this.columnOptions = columnOptions;
return this;
}
@Override
public String convertToCommand() {
if (this.m == 0 && this.d == 0) {
return Strings.replaceWithOrder("`{0}` {1}{2}", columnName, columnType.name().toLowerCase(), convertToOptions());
} else if (this.d == 0) {
return Strings.replaceWithOrder("`{0}` {1}({2}){3}", columnName, columnType.name().toLowerCase(), m, convertToOptions());
} else {
return Strings.replaceWithOrder("`{0}` {1}({2},{3}){4}", columnName, columnType.name().toLowerCase(), m, d, convertToOptions());
}
}
private String convertToOptions() {
StringBuilder builder = new StringBuilder();
Arrays.stream(columnOptions).forEach(option -> builder.append(" ").append(option.getText()));
if (defaultValue != null) {
if (defaultValue instanceof String) {
builder.append(" DEFAULT '").append(defaultValue).append("'");
} else {
builder.append(" DEFAULT ").append(defaultValue);
}
}
return builder.toString();
}
@Override
public String toString() {
return "SQLColumn{" +
"columnType=" + columnType +
", m=" + m +
", d=" + d +
", columnName='" + columnName + '\'' +
", defaultValue=" + defaultValue +
", columnOptions=" + Arrays.toString(columnOptions) +
'}';
}
}

View File

@@ -0,0 +1,38 @@
package io.izzel.taboolib.module.mysql.builder;
/**
* @Author sky
* @Since 2018-05-14 21:43
*/
public enum SQLColumnOption {
/**
* 不能为空
*/
NOTNULL("NOT NULL"),
/**
* 唯一
*/
UNIQUE_KEY("UNIQUE KEY"),
/**
* 主键
*/
PRIMARY_KEY("PRIMARY KEY"),
/**
* 递增
*/
AUTO_INCREMENT("AUTO_INCREMENT");
String text;
SQLColumnOption(String text) {
this.text = text;
}
public String getText() {
return text;
}
}

View File

@@ -0,0 +1,122 @@
package io.izzel.taboolib.module.mysql.builder;
/**
* @Author sky
* @Since 2018-05-14 19:13
*/
public enum SQLColumnType {
/**
* 有符号值:-128 到127- 27 到27 - 1
* 无符号值0到2550 到28 - 1 1个字节
*/
TINYINT,
/**
* 有符号值:-32768 到32767- 215 到215 - 1
* 无符号值0到655350 到21 6 - 1 2个字节
*/
SMALLINT,
/**
* 有符号值:-8388608 到8388607- 22 3 到22 3 - 1
* 无符号值0到167772150 到22 4 - 1 3个字节
*/
MEDIUMINT,
/**
* 有符号值:-2147683648 到2147683647- 231 到231- 1
* 无符号值0到42949672950 到232 - 1 4个字节
*/
INT,
/**
* 有符号值:-9223372036854775808 到9223373036854775807- 263到263-1
* 无符号值0到184467440737095516150到264 1 8个字节
*/
BIGINT,
/**
* 最小非零值±1.175494351e - 38
*/
FLOAT,
/**
* 最小非零值±2.2250738585072014e - 308
*/
DOUBLE,
/**
* 可变其值的范围依赖于m 和d
*/
DECIMAL,
/**
* 定长:磁盘空间比较浪费,但是效率高,确定数据长度都一样,就使用定长
* 比如:电话号码,身份证号
* 最长可取255
*/
CHAR,
/**
* 边长:比较节省空间,但是效率低,数据不能确定长度(不同数据长度有变化)
* 比如:地址
* 最长可取65535
*/
VARCHAR,
/**
* 0~255字节值的长度+2字节
*/
TINYTEXT,
/**
* 0~65535字节值的长度+2字节
*/
TEXT,
/**
* 0~167772150字节值的长度+3字节
*/
MEDIUMTEXT,
/**
* 0~4294967295字节值的长度+4字节
*/
LONGTEXT,
/**
* 字节数为M允许长度为0~M的定长二进制字符串
*/
BINARY,
/**
* 允许长度为0~M的变长二进制字符串字节数为值的长度加1
*/
VARBINARY,
/**
* M位二进制数据M最大值为64
*/
BIT,
/**
* 可变长二进制数据最多255个字节
*/
TINYBLOB,
/**
* 可变长二进制数据最多2的16次方-1个字节
*/
BLOB,
/**
* 可变长二进制数据最多2的24次方-1个字节
*/
MEDIUMBLOB,
/**
* 可变长二进制数据最多2的32次方-1个字节
*/
LONGBLOB
}

View File

@@ -0,0 +1,36 @@
package io.izzel.taboolib.module.mysql.builder;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
/**
* @Author sky
* @Since 2018-06-22 16:38
*/
public class SQLExecutor {
public static void freeConnection(Connection connection) {
try {
if (connection != null) {
connection.close();
}
} catch (Exception ignored) {
}
}
public static void freeStatement(PreparedStatement preparedStatement, ResultSet resultSet) {
try {
if (preparedStatement != null) {
preparedStatement.close();
}
} catch (Exception ignored) {
}
try {
if (resultSet != null) {
resultSet.close();
}
} catch (Exception ignored) {
}
}
}

View File

@@ -0,0 +1,127 @@
package io.izzel.taboolib.module.mysql.builder;
import io.izzel.taboolib.module.mysql.IHost;
import io.izzel.taboolib.util.Strings;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.plugin.Plugin;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
/**
* @Author sky
* @Since 2018-05-14 19:01
*/
public class SQLHost extends IHost {
private String host;
private String user;
private String port;
private String password;
private String database;
private List<String> flags = Arrays.asList("characterEncoding=utf-8", "useSSL=false");
public SQLHost(ConfigurationSection section, Plugin plugin) {
this(section, plugin, false);
}
public SQLHost(ConfigurationSection section, Plugin plugin, boolean autoClose) {
this(section.getString("host", "localhost"), section.getString("user", "root"), section.getString("port", "3306"), section.getString("password", ""), section.getString("database", "test"), plugin);
}
public SQLHost(String host, int port, String user, String password, String database, Plugin plugin) {
this(host, user, String.valueOf(port), password, database, plugin, false);
}
@Deprecated
public SQLHost(String host, String user, String port, String password, String database, Plugin plugin) {
this(host, user, port, password, database, plugin, false);
}
public SQLHost(String host, String user, String port, String password, String database, Plugin plugin, boolean autoClose) {
super(plugin, autoClose);
this.host = host;
this.user = user;
this.port = port;
this.password = password;
this.database = database;
}
@Override
public String getConnectionUrl() {
return Strings.replaceWithOrder("jdbc:mysql://{0}:{1}/{2}" + getFlagsInUrl(), this.host, this.port, this.database);
}
@Override
public String getConnectionUrlSimple() {
return Strings.replaceWithOrder("jdbc:mysql://{0}:{1}/{2}", this.host, this.port, this.database);
}
public String getHost() {
return host;
}
public String getUser() {
return user;
}
public String getPort() {
return port;
}
public String getPassword() {
return password;
}
public String getDatabase() {
return database;
}
public List<String> getFlags() {
return flags;
}
public String getFlagsInUrl() {
if (flags.isEmpty()) {
return "";
}
String collect = flags.stream().map(f -> f + "&").collect(Collectors.joining());
return "?" + collect.substring(0, collect.length() - 1);
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof SQLHost)) {
return false;
}
SQLHost sqlHost = (SQLHost) o;
return Objects.equals(getHost(), sqlHost.getHost()) &&
Objects.equals(getUser(), sqlHost.getUser()) &&
Objects.equals(getPort(), sqlHost.getPort()) &&
Objects.equals(getPassword(), sqlHost.getPassword()) &&
Objects.equals(getDatabase(), sqlHost.getDatabase()) &&
Objects.equals(getFlags(), sqlHost.getFlags());
}
@Override
public int hashCode() {
return Objects.hash(getHost(), getUser(), getPort(), getPassword(), getDatabase(), getFlags());
}
@Override
public String toString() {
return "SQLHost{" +
"host='" + host + '\'' +
", user='" + user + '\'' +
", port='" + port + '\'' +
", password='" + password + '\'' +
", database='" + database + '\'' +
", flags=" + flags +
'}';
}
}

View File

@@ -0,0 +1,98 @@
package io.izzel.taboolib.module.mysql.builder;
import io.izzel.taboolib.module.mysql.IColumn;
import io.izzel.taboolib.module.mysql.builder.query.RunnableQuery;
import io.izzel.taboolib.module.mysql.builder.query.RunnableUpdate;
import io.izzel.taboolib.util.ArrayUtil;
import io.izzel.taboolib.util.Strings;
/**
* @Author sky
* @Since 2018-05-14 19:07
*/
public class SQLTable {
private String tableName;
private IColumn[] columns;
public SQLTable(String tableName) {
this.tableName = tableName;
}
public SQLTable(String tableName, IColumn... column) {
this.tableName = tableName;
this.columns = column;
}
public SQLTable(String tableName, SQLColumn... column) {
this.tableName = tableName;
this.columns = column;
}
public SQLTable column(IColumn column) {
columns = columns == null ? new IColumn[] {column} : ArrayUtil.arrayAppend(columns, column);
return this;
}
@Deprecated
public SQLTable addColumn(SQLColumn sqlColumn) {
columns = columns == null ? new SQLColumn[] {sqlColumn} : ArrayUtil.arrayAppend(columns, sqlColumn);
return this;
}
public String createQuery() {
StringBuilder builder = new StringBuilder();
java.util.Arrays.stream(columns).forEach(sqlColumn -> builder.append(sqlColumn.convertToCommand()).append(", "));
return Strings.replaceWithOrder("create table if not exists `{0}` ({1})", tableName, builder.substring(0, builder.length() - 2));
}
public String deleteQuery() {
return Strings.replaceWithOrder("drop table if exists `{0}`", tableName);
}
public String cleanQuery() {
return Strings.replaceWithOrder("delete from `{0}`", tableName);
}
public String truncateQuery() {
return Strings.replaceWithOrder("truncate table `{0}`", tableName);
}
public RunnableQuery executeQuery(String query) {
return new RunnableQuery(query);
}
public RunnableQuery executeSelect() {
return executeQuery("select * from " + tableName);
}
public RunnableQuery executeSelect(String queryWhere) {
return executeQuery("select * from " + tableName + " where " + queryWhere);
}
public RunnableUpdate executeInsert(String queryValues) {
return executeUpdate("insert into " + tableName + " values(" + queryValues + ")");
}
public RunnableUpdate executeUpdate(String query) {
return new RunnableUpdate(query);
}
public RunnableUpdate executeUpdate(String update, String where) {
return executeUpdate("update " + tableName + " set " + update + " where " + where);
}
// *********************************
//
// Getter and Setter
//
// *********************************
public String getTableName() {
return tableName;
}
public IColumn[] getColumns() {
return columns;
}
}

View File

@@ -0,0 +1,132 @@
package io.izzel.taboolib.module.mysql.builder.query;
import io.izzel.taboolib.module.logger.TLogger;
import io.izzel.taboolib.module.mysql.builder.SQLExecutor;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* @Author sky
* @Since 2018-07-03 21:29
*/
public class RunnableQuery {
private DataSource dataSource;
private TaskStatement statement;
private TaskResult result;
private TaskResult resultNext;
private TaskResult resultAutoNext;
private Connection connection;
private boolean autoClose;
private String query;
public RunnableQuery(String query) {
this.query = query;
}
public RunnableQuery dataSource(DataSource dataSource) {
this.dataSource = dataSource;
return this;
}
public RunnableQuery statement(TaskStatement statement) {
this.statement = statement;
return this;
}
public RunnableQuery result(TaskResult result) {
this.result = result;
return this;
}
public RunnableQuery resultNext(TaskResult result) {
this.resultNext = result;
return this;
}
public RunnableQuery resultAutoNext(TaskResult result) {
this.resultAutoNext = result;
return this;
}
public RunnableQuery connection(Connection connection) {
return connection(connection, false);
}
public RunnableQuery connection(Connection connection, boolean autoClose) {
this.connection = connection;
this.autoClose = autoClose;
return this;
}
public <T> T run(Object def, T translate) {
Object object = run(def);
return object == null ? def == null ? null : (T) def : (T) object;
}
public Object run() {
return run(null);
}
public Object run(Object def) {
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
if (dataSource != null) {
try (Connection connection = dataSource.getConnection()) {
preparedStatement = connection.prepareStatement(query);
if (statement != null) {
statement.execute(preparedStatement);
}
resultSet = preparedStatement.executeQuery();
return getResult(resultSet);
} catch (Exception e) {
printException(e);
} finally {
SQLExecutor.freeStatement(preparedStatement, resultSet);
}
} else if (connection != null) {
try {
preparedStatement = connection.prepareStatement(query);
if (statement != null) {
statement.execute(preparedStatement);
}
resultSet = preparedStatement.executeQuery();
return getResult(resultSet);
} catch (Exception e) {
printException(e);
} finally {
SQLExecutor.freeStatement(preparedStatement, resultSet);
if (autoClose) {
SQLExecutor.freeConnection(connection);
}
}
}
return def;
}
private void printException(Exception e) {
TLogger.getGlobalLogger().error("An exception occurred in the database. (" + query + ")");
TLogger.getGlobalLogger().error("Reason: " + e.toString());
e.printStackTrace();
}
private Object getResult(ResultSet resultSet) throws SQLException {
if (resultNext != null && resultSet.next()) {
return resultNext.execute(resultSet);
} else if (result != null) {
return result.execute(resultSet);
} else if (resultAutoNext != null) {
Object result = null;
while (resultSet.next()) {
result = resultAutoNext.execute(resultSet);
}
return result;
} else {
return null;
}
}
}

View File

@@ -0,0 +1,85 @@
package io.izzel.taboolib.module.mysql.builder.query;
import io.izzel.taboolib.module.logger.TLogger;
import io.izzel.taboolib.module.mysql.builder.SQLExecutor;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
/**
* F
*
* @Author sky
* @Since 2018-07-03 21:29
*/
public class RunnableUpdate {
private DataSource dataSource;
private TaskStatement statement;
private Connection connection;
private boolean autoClose;
private String query;
public RunnableUpdate(String query) {
this.query = query;
}
public RunnableUpdate dataSource(DataSource dataSource) {
this.dataSource = dataSource;
return this;
}
public RunnableUpdate statement(TaskStatement task) {
this.statement = task;
return this;
}
public RunnableUpdate connection(Connection connection) {
return connection(connection, false);
}
public RunnableUpdate connection(Connection connection, boolean autoClose) {
this.connection = connection;
this.autoClose = autoClose;
return this;
}
public void run() {
PreparedStatement preparedStatement = null;
if (dataSource != null) {
try (Connection connection = dataSource.getConnection()) {
preparedStatement = connection.prepareStatement(query);
if (statement != null) {
statement.execute(preparedStatement);
}
preparedStatement.executeUpdate();
} catch (Exception e) {
printException(e);
} finally {
SQLExecutor.freeStatement(preparedStatement, null);
}
} else if (connection != null) {
try {
preparedStatement = connection.prepareStatement(query);
if (statement != null) {
statement.execute(preparedStatement);
}
preparedStatement.executeUpdate();
} catch (Exception e) {
printException(e);
} finally {
SQLExecutor.freeStatement(preparedStatement, null);
if (autoClose) {
SQLExecutor.freeConnection(connection);
}
}
}
}
private void printException(Exception e) {
TLogger.getGlobalLogger().error("An exception occurred in the database. (" + query + ")");
TLogger.getGlobalLogger().error("Reason: " + e.toString());
e.printStackTrace();
}
}

View File

@@ -0,0 +1,14 @@
package io.izzel.taboolib.module.mysql.builder.query;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* @Author sky
* @Since 2018-07-03 22:02
*/
public interface TaskResult {
Object execute(ResultSet resultSet) throws SQLException;
}

View File

@@ -0,0 +1,14 @@
package io.izzel.taboolib.module.mysql.builder.query;
import java.sql.PreparedStatement;
import java.sql.SQLException;
/**
* @Author sky
* @Since 2018-07-03 22:02
*/
public interface TaskStatement {
void execute(PreparedStatement preparedStatement) throws SQLException;
}

View File

@@ -0,0 +1,99 @@
package io.izzel.taboolib.module.mysql.hikari;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import io.izzel.taboolib.locale.TLocale;
import io.izzel.taboolib.module.config.TConfig;
import io.izzel.taboolib.module.inject.TInject;
import io.izzel.taboolib.module.mysql.IHost;
import io.izzel.taboolib.module.mysql.builder.SQLHost;
import io.izzel.taboolib.module.mysql.lite.SQLiteHost;
import org.bukkit.configuration.file.FileConfiguration;
import javax.sql.DataSource;
import java.util.concurrent.ConcurrentHashMap;
/**
* @Author sky
* @Since 2018-05-16 21:59
*/
public class HikariHandler {
@TInject("datasource.yml")
private static TConfig settings;
private static ConcurrentHashMap<IHost, MapDataSource> dataSource = new ConcurrentHashMap<>();
public static DataSource createDataSource(IHost host) {
return createDataSource(host, null);
}
public static HikariDataSource createDataSource(IHost host, HikariConfig hikariConfig) {
MapDataSource mapDataSource = dataSource.computeIfAbsent(host, x -> new MapDataSource(x, new HikariDataSource(hikariConfig == null ? createConfig(host) : hikariConfig)));
mapDataSource.getActivePlugin().getAndIncrement();
if (mapDataSource.getActivePlugin().get() == 1) {
TLocale.Logger.info("MYSQL-HIKARI.CREATE-SUCCESS", host.getPlugin().getName(), host.getConnectionUrlSimple());
} else {
TLocale.Logger.info("MYSQL-HIKARI.CREATE-EXISTS", host.getPlugin().getName(), mapDataSource.getHost().getPlugin().getName());
}
return mapDataSource.getHikariDataSource();
}
public static void closeDataSourceForce() {
dataSource.values().forEach(x -> x.getHikariDataSource().close());
}
public static void closeDataSource(IHost host) {
if (host != null && dataSource.containsKey(host)) {
MapDataSource mapDataSource = dataSource.get(host);
if (mapDataSource.getActivePlugin().getAndDecrement() <= 1) {
mapDataSource.getHikariDataSource().close();
dataSource.remove(host);
TLocale.Logger.info("MYSQL-HIKARI.CLOSE-SUCCESS", host.getPlugin().getName(), host.getConnectionUrlSimple());
} else {
TLocale.Logger.info("MYSQL-HIKARI.CLOSE-FAIL", host.getPlugin().getName(), String.valueOf(mapDataSource.getActivePlugin().get()));
}
}
}
public static HikariConfig createConfig(IHost host) {
HikariConfig config = new HikariConfig();
config.setJdbcUrl(host.getConnectionUrl());
if (host instanceof SQLHost) {
config.setDriverClassName(settings.getString("DefaultSettings.DriverClassName", "com.mysql.jdbc.Driver"));
config.setUsername(((SQLHost) host).getUser());
config.setPassword(((SQLHost) host).getPassword());
} else if (host instanceof SQLiteHost) {
config.setDriverClassName("org.sqlite.JDBC");
} else {
throw new IllegalArgumentException("Invalid host: " + host.getClass().getName());
}
config.setAutoCommit(settings.getBoolean("DefaultSettings.AutoCommit", true));
config.setMinimumIdle(settings.getInt("DefaultSettings.MinimumIdle", 1));
config.setMaximumPoolSize(settings.getInt("DefaultSettings.MaximumPoolSize", 10));
config.setValidationTimeout(settings.getInt("DefaultSettings.ValidationTimeout", 5000));
config.setConnectionTimeout(settings.getInt("DefaultSettings.ConnectionTimeout", 30000));
config.setIdleTimeout(settings.getInt("DefaultSettings.IdleTimeout", 600000));
config.setMaxLifetime(settings.getInt("DefaultSettings.MaxLifetime", 1800000));
if (settings.contains("DefaultSettings.ConnectionTestQuery")) {
config.setConnectionTestQuery(settings.getString("DefaultSettings.ConnectionTestQuery"));
}
if (settings.contains("DefaultSettings.DataSourceProperty")) {
settings.getConfigurationSection("DefaultSettings.DataSourceProperty").getKeys(false).forEach(key -> config.addDataSourceProperty(key, settings.getString("DefaultSettings.DataSourceProperty." + key)));
}
return config;
}
// *********************************
//
// Getter and Setter
//
// *********************************
public static ConcurrentHashMap<IHost, MapDataSource> getDataSource() {
return dataSource;
}
public static FileConfiguration getSettings() {
return settings;
}
}

View File

@@ -0,0 +1,35 @@
package io.izzel.taboolib.module.mysql.hikari;
import com.zaxxer.hikari.HikariDataSource;
import io.izzel.taboolib.module.mysql.IHost;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @Author sky
* @Since 2018-05-17 23:47
*/
public class MapDataSource {
private IHost host;
private AtomicInteger activePlugin;
private HikariDataSource hikariDataSource;
MapDataSource(IHost host, HikariDataSource hikariDataSource) {
this.host = host;
this.activePlugin = new AtomicInteger();
this.hikariDataSource = hikariDataSource;
}
public IHost getHost() {
return host;
}
public AtomicInteger getActivePlugin() {
return activePlugin;
}
public HikariDataSource getHikariDataSource() {
return hikariDataSource;
}
}

View File

@@ -0,0 +1,126 @@
package io.izzel.taboolib.module.mysql.lite;
import io.izzel.taboolib.util.Strings;
import io.izzel.taboolib.module.mysql.IColumn;
import java.util.Arrays;
/**
* @Author sky
* @Since 2018-05-14 19:09
*/
public class SQLiteColumn extends IColumn {
public static final SQLiteColumn PRIMARY_KEY_ID = new SQLiteColumn(SQLiteColumnType.INTEGER, "id", SQLiteColumnOption.NOTNULL, SQLiteColumnOption.PRIMARY_KEY, SQLiteColumnOption.AUTOINCREMENT);
private SQLiteColumnType columnType;
private int m;
private int d;
private String columnName;
private Object defaultValue;
private SQLiteColumnOption[] columnOptions;
/**
* 文本 类型常用构造器
* new SQLColumn(SQLiteColumnType.TEXT, "username");
*/
public SQLiteColumn(SQLiteColumnType columnType, String columnName) {
this(columnType, 0, 0, columnName, null);
}
/**
* 主键 类型常用构造器
* new SQLColumn(SQLiteColumnType.TEXT, "username", SQLiteColumnOption.PRIMARY_KEY, SQLiteColumnOption.AUTO_INCREMENT);
*/
public SQLiteColumn(SQLiteColumnType columnType, String columnName, SQLiteColumnOption... columnOptions) {
this(columnType, 0, 0, columnName, null, columnOptions);
}
/**
* 数据 类型常用构造器
* new SQLColumn(SQLiteColumnType.TEXT, "player_group", "PLAYER");
*/
public SQLiteColumn(SQLiteColumnType columnType, String columnName, Object defaultValue) {
this(columnType, 0, 0, columnName, defaultValue);
}
public SQLiteColumn(SQLiteColumnType columnType, String columnName, Object defaultValue, SQLiteColumnOption... columnOptions) {
this(columnType, 0, 0, columnName, defaultValue, columnOptions);
}
/**
* 完整构造器
*
* @param columnType 类型
* @param m m值
* @param d d值
* @param columnName 名称
* @param defaultValue 默认值
* @param columnOptions 属性值
*/
public SQLiteColumn(SQLiteColumnType columnType, int m, int d, String columnName, Object defaultValue, SQLiteColumnOption... columnOptions) {
this.columnType = columnType;
this.m = m;
this.d = d;
this.columnName = columnName;
this.defaultValue = defaultValue;
this.columnOptions = columnOptions;
}
public SQLiteColumn m(int m) {
this.m = m;
return this;
}
public SQLiteColumn d(int d) {
this.d = d;
return this;
}
public SQLiteColumn defaultValue(Object defaultValue) {
this.defaultValue = defaultValue;
return this;
}
public SQLiteColumn columnOptions(SQLiteColumnOption... columnOptions) {
this.columnOptions = columnOptions;
return this;
}
public String convertToCommand() {
if (this.m == 0 && this.d == 0) {
return Strings.replaceWithOrder("`{0}` {1}{2}", columnName, columnType.name().toLowerCase(), convertToOptions());
} else if (this.d == 0) {
return Strings.replaceWithOrder("`{0}` {1}({2}){3}", columnName, columnType.name().toLowerCase(), m, convertToOptions());
} else {
return Strings.replaceWithOrder("`{0}` {1}({2},{3}){4}", columnName, columnType.name().toLowerCase(), m, d, convertToOptions());
}
}
private String convertToOptions() {
StringBuilder builder = new StringBuilder();
Arrays.stream(columnOptions).forEach(option -> builder.append(" ").append(option.getText()));
if (defaultValue != null) {
if (defaultValue instanceof String) {
builder.append(" DEFAULT '").append(defaultValue).append("'");
} else {
builder.append(" DEFAULT ").append(defaultValue);
}
}
return builder.toString();
}
@Override
public String toString() {
return "SQLiteColumn{" +
"columnType=" + columnType +
", m=" + m +
", d=" + d +
", columnName='" + columnName + '\'' +
", defaultValue=" + defaultValue +
", columnOptions=" + Arrays.toString(columnOptions) +
'}';
}
}

View File

@@ -0,0 +1,38 @@
package io.izzel.taboolib.module.mysql.lite;
/**
* @Author sky
* @Since 2018-05-14 21:43
*/
public enum SQLiteColumnOption {
/**
* 不能为空
*/
NOTNULL("NOT NULL"),
/**
* 唯一
*/
UNIQUE("UNIQUE"),
/**
* 主键
*/
PRIMARY_KEY("PRIMARY KEY"),
/**
* 递增
*/
AUTOINCREMENT("AUTOINCREMENT");
String text;
SQLiteColumnOption(String text) {
this.text = text;
}
public String getText() {
return text;
}
}

View File

@@ -0,0 +1,36 @@
package io.izzel.taboolib.module.mysql.lite;
/**
* @Author 坏黑
* @Since 2018-12-08 13:28
*/
public enum SQLiteColumnType {
NULL,
/**
* 带符号的整数,根据值的大小存储在 1、2、3、4、6 或 8 字节中。
*/
INTEGER,
/**
* 浮点值,存储为 8 字节的 IEEE 浮点数字。
*/
REAL,
/**
* 文本字符串使用数据库编码UTF-8、UTF-16BE 或 UTF-16LE存储。
*/
TEXT,
/**
* blob 数据,完全根据它的输入存储。
*/
BLOB,
/**
* 数字自动转换
*/
NUMERIC
}

View File

@@ -0,0 +1,64 @@
package io.izzel.taboolib.module.mysql.lite;
import io.izzel.taboolib.module.mysql.IHost;
import org.bukkit.plugin.Plugin;
import java.io.File;
import java.util.Objects;
/**
* @Author 坏黑
* @Since 2018-12-08 12:58
*/
public class SQLiteHost extends IHost {
private final File file;
public SQLiteHost(File file, Plugin plugin) {
super(plugin);
this.file = file;
}
public SQLiteHost(File file, Plugin plugin, boolean autoClose) {
super(plugin, autoClose);
this.file = file;
}
public File getFile() {
return file;
}
@Override
public String getConnectionUrl() {
return "jdbc:sqlite:" + file.getPath();
}
@Override
public String getConnectionUrlSimple() {
return "jdbc:sqlite:" + file.getPath();
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof SQLiteHost)) {
return false;
}
SQLiteHost that = (SQLiteHost) o;
return Objects.equals(getFile(), that.getFile());
}
@Override
public int hashCode() {
return Objects.hash(getFile());
}
@Override
public String toString() {
return "SQLiteHost{" +
"file=" + file +
'}';
}
}

View File

@@ -0,0 +1,57 @@
package io.izzel.taboolib.module.nms;
import io.izzel.taboolib.module.inject.TFunction;
import io.izzel.taboolib.module.lite.SimpleVersionControl;
import io.izzel.taboolib.module.nms.nbt.NBTCompound;
import org.bukkit.Particle;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
/**
* @Author 坏黑
* @Since 2018-11-09 14:38
*/
@TFunction(enable = "init")
public abstract class NMSHandler {
private static NMSHandler handler;
public static NMSHandler getHandler() {
return handler;
}
static void init() {
try {
handler = (NMSHandler) SimpleVersionControl.createNMS("io.izzel.taboolib.module.nms.NMSHandlerImpl").translate().newInstance();
} catch (Exception e) {
e.printStackTrace();
}
}
abstract public boolean isRunning();
abstract public Object toPacketPlayOutWorldParticles(Particle var1, boolean var2, float var3, float var4, float var5, float var6, float var7, float var8, float var9, int var10, Object var11);
abstract public double[] getTPS();
abstract public String getName(ItemStack itemStack);
abstract public String getName(Entity entity);
abstract public void sendTitle(Player player, String title, int titleFadein, int titleStay, int titleFadeout, String subtitle, int subtitleFadein, int subtitleStay, int subtitleFadeout);
abstract public void sendActionBar(Player player, String text);
abstract public Object _NBT(ItemStack itemStack);
abstract public ItemStack _NBT(ItemStack itemStack, Object compound);
public NBTCompound loadNBT(ItemStack itemStack) {
return (NBTCompound) _NBT(itemStack);
}
public ItemStack saveNBT(ItemStack itemStack, NBTCompound compound) {
return _NBT(itemStack, compound);
}
}

View File

@@ -0,0 +1,303 @@
package io.izzel.taboolib.module.nms;
import io.izzel.taboolib.Version;
import io.izzel.taboolib.module.lite.SimpleReflection;
import io.izzel.taboolib.module.nms.nbt.NBTCompound;
import io.izzel.taboolib.module.nms.nbt.NBTList;
import io.izzel.taboolib.module.packet.TPacketHandler;
import net.minecraft.server.v1_12_R1.ChatMessageType;
import net.minecraft.server.v1_12_R1.EntityVillager;
import net.minecraft.server.v1_12_R1.MinecraftServer;
import net.minecraft.server.v1_12_R1.NBTTagCompound;
import net.minecraft.server.v1_13_R2.IRegistry;
import net.minecraft.server.v1_8_R3.*;
import org.bukkit.Bukkit;
import org.bukkit.Particle;
import org.bukkit.craftbukkit.v1_12_R1.CraftParticle;
import org.bukkit.craftbukkit.v1_13_R2.CraftServer;
import org.bukkit.craftbukkit.v1_13_R2.entity.CraftVillager;
import org.bukkit.craftbukkit.v1_8_R3.inventory.CraftItemStack;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.entity.Villager;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.PotionMeta;
import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;
/**
* @Author 坏黑
* @Since 2018-11-09 14:42
*/
public class NMSHandlerImpl extends NMSHandler {
private Field entityTypesField;
static {
SimpleReflection.saveField(NBTTagString.class);
SimpleReflection.saveField(NBTTagDouble.class);
SimpleReflection.saveField(NBTTagInt.class);
SimpleReflection.saveField(NBTTagFloat.class);
SimpleReflection.saveField(NBTTagShort.class);
SimpleReflection.saveField(NBTTagLong.class);
SimpleReflection.saveField(NBTTagByte.class);
SimpleReflection.saveField(NBTTagIntArray.class);
SimpleReflection.saveField(NBTTagByteArray.class);
SimpleReflection.saveField(NBTTagList.class);
SimpleReflection.saveField(NBTTagCompound.class);
}
public NMSHandlerImpl() {
if (Version.isAfter(Version.v1_13)) {
SimpleReflection.saveField(net.minecraft.server.v1_12_R1.Entity.class);
for (Field declaredField : SimpleReflection.getFields(net.minecraft.server.v1_12_R1.Entity.class).values()) {
if (declaredField.getType().getSimpleName().equals("EntityTypes")) {
entityTypesField = declaredField;
break;
}
}
}
SimpleReflection.saveField(MinecraftServer.class);
}
@Override
public boolean isRunning() {
return !SimpleReflection.getFieldValue(MinecraftServer.class, ((CraftServer) Bukkit.getServer()).getServer(), "hasStopped", false);
}
@Override
public Object toPacketPlayOutWorldParticles(Particle var1, boolean var2, float var3, float var4, float var5, float var6, float var7, float var8, float var9, int var10, Object var11) {
return new net.minecraft.server.v1_12_R1.PacketPlayOutWorldParticles(CraftParticle.toNMS(var1), var2, var3, var4, var5, var6, var7, var8, var9, var10, CraftParticle.toData(var1, var11));
}
@Override
public double[] getTPS() {
return MinecraftServer.getServer().recentTps;
}
@Override
public String getName(ItemStack itemStack) {
Object nmsItem = CraftItemStack.asNMSCopy(itemStack);
if (Version.isAfter(Version.v1_13)) {
String name = ((net.minecraft.server.v1_8_R3.ItemStack) nmsItem).getItem().getName();
if (itemStack.getItemMeta() instanceof PotionMeta) {
name += ".effect." + ((net.minecraft.server.v1_8_R3.ItemStack) nmsItem).getTag().getString("Potion").replaceAll("minecraft:(strong_|long_)?", "");
}
return name;
} else if (Version.isAfter(Version.v1_11)) {
String name = ((net.minecraft.server.v1_12_R1.ItemStack) nmsItem).getItem().a((net.minecraft.server.v1_12_R1.ItemStack) nmsItem);
if (itemStack.getItemMeta() instanceof PotionMeta) {
return name.replace("item.", "") + ".effect." + ((net.minecraft.server.v1_8_R3.ItemStack) nmsItem).getTag().getString("Potion").replaceAll("(minecraft:)?(strong_|long_)?", "");
}
return name + ".name";
} else {
String name = ((net.minecraft.server.v1_8_R3.ItemStack) nmsItem).getItem().getName();
if (itemStack.getItemMeta() instanceof PotionMeta) {
return name.replace("item.", "") + ".effect." + ((net.minecraft.server.v1_8_R3.ItemStack) nmsItem).getTag().getString("Potion").replaceAll("(minecraft:)?(strong_|long_)?", "");
}
return name + ".name";
}
}
@Override
public String getName(Entity entity) {
if (Version.isAfter(Version.v1_14)) {
net.minecraft.server.v1_14_R1.MinecraftKey minecraftKey = net.minecraft.server.v1_14_R1.EntityTypes.getName(((org.bukkit.craftbukkit.v1_14_R1.entity.CraftEntity) entity).getHandle().getEntityType());
return "entity.minecraft." + minecraftKey.getKey();
} else if (Version.isAfter(Version.v1_13)) {
try {
String name = "entity.minecraft." + IRegistry.ENTITY_TYPE.getKey((net.minecraft.server.v1_13_R2.EntityTypes<?>) entityTypesField.get(((org.bukkit.craftbukkit.v1_13_R2.entity.CraftEntity) entity).getHandle())).getKey();
if (entity instanceof Villager && ((CraftVillager) entity).getCareer() != null) {
name += "." + String.valueOf(((CraftVillager) entity).getCareer()).toLowerCase();
}
return name;
} catch (Throwable t) {
t.printStackTrace();
}
return "entity.null";
} else {
try {
if (entity instanceof Player) {
return "entity.Player.name";
}
if (entity instanceof Villager) {
String name = "name";
Object villager = ((org.bukkit.craftbukkit.v1_12_R1.entity.CraftVillager) entity).getHandle();
Object export = new NBTTagCompound();
((EntityVillager) villager).b((NBTTagCompound) export);
int career = ((NBTTagCompound) export).getInt("Career");
switch (((EntityVillager) villager).getProfession()) {
case 0:
if (career == 1) {
name = "farmer";
} else if (career == 2) {
name = "fisherman";
} else if (career == 3) {
name = "shepherd";
} else if (career == 4) {
name = "fletcher";
}
break;
case 1:
if (career == 1) {
name = "librarian";
} else if (career == 2) {
name = "cartographer";
}
break;
case 2:
name = "cleric";
break;
case 3:
if (career == 1) {
name = "armor";
} else if (career == 2) {
name = "weapon";
} else if (career == 3) {
name = "tool";
}
break;
case 4:
if (career == 1) {
name = "butcher";
} else if (career == 2) {
name = "leather";
}
break;
case 5:
name = "nitwit";
break;
}
return "entity.Villager." + name;
}
return "entity." + entity.getType().getEntityClass().getSimpleName() + ".name";
} catch (Throwable t) {
t.printStackTrace();
}
return "entity.null";
}
}
@Override
public void sendTitle(Player player, String title, int titleFadein, int titleStay, int titleFadeout, String subtitle, int subtitleFadein, int subtitleStay, int subtitleFadeout) {
TPacketHandler.sendPacket(player, new PacketPlayOutTitle(PacketPlayOutTitle.EnumTitleAction.TIMES, new ChatComponentText(String.valueOf(title)), titleFadein, titleStay, titleFadeout));
TPacketHandler.sendPacket(player, new PacketPlayOutTitle(PacketPlayOutTitle.EnumTitleAction.TITLE, new ChatComponentText(String.valueOf(title)), titleFadein, titleStay, titleFadeout));
TPacketHandler.sendPacket(player, new PacketPlayOutTitle(PacketPlayOutTitle.EnumTitleAction.TIMES, new ChatComponentText(String.valueOf(subtitle)), subtitleFadein, subtitleStay, subtitleFadeout));
TPacketHandler.sendPacket(player, new PacketPlayOutTitle(PacketPlayOutTitle.EnumTitleAction.SUBTITLE, new ChatComponentText(String.valueOf(subtitle)), subtitleFadein, subtitleStay, subtitleFadeout));
}
@Override
public void sendActionBar(Player player, String text) {
if (Version.isAfter(Version.v1_12)) {
TPacketHandler.sendPacket(player, new net.minecraft.server.v1_12_R1.PacketPlayOutChat(new net.minecraft.server.v1_12_R1.ChatComponentText(String.valueOf(text)), ChatMessageType.GAME_INFO));
} else {
TPacketHandler.sendPacket(player, new PacketPlayOutChat(new ChatComponentText(String.valueOf(text)), (byte) 2));
}
}
@Override
public ItemStack _NBT(ItemStack itemStack, Object compound) {
Object nmsItem = CraftItemStack.asNMSCopy(itemStack);
try {
((net.minecraft.server.v1_8_R3.ItemStack) nmsItem).setTag((net.minecraft.server.v1_8_R3.NBTTagCompound) toNBTBase((io.izzel.taboolib.module.nms.nbt.NBTBase) compound));
} catch (Throwable t) {
t.printStackTrace();
}
return CraftItemStack.asBukkitCopy((net.minecraft.server.v1_8_R3.ItemStack) nmsItem);
}
@Override
public Object _NBT(ItemStack itemStack) {
Object nmsItem = CraftItemStack.asNMSCopy(itemStack);
try {
return ((net.minecraft.server.v1_8_R3.ItemStack) nmsItem).hasTag() ? fromNBTBase(((net.minecraft.server.v1_8_R3.ItemStack) nmsItem).getTag()) : new NBTCompound();
} catch (Throwable t) {
t.printStackTrace();
}
return new NBTCompound();
}
private Object toNBTBase(io.izzel.taboolib.module.nms.nbt.NBTBase base) {
switch (base.getType().getId()) {
case 1:
return new NBTTagByte(base.asByte());
case 2:
return new NBTTagShort(base.asShort());
case 3:
return new NBTTagInt(base.asInt());
case 4:
return new NBTTagLong(base.asLong());
case 5:
return new NBTTagFloat(base.asFloat());
case 6:
return new NBTTagDouble(base.asDouble());
case 7:
return new NBTTagByteArray(base.asByteArray());
case 11:
return new NBTTagIntArray(base.asIntArray());
case 8:
return new NBTTagString(base.asString());
case 9:
Object nmsList = new NBTTagList();
for (io.izzel.taboolib.module.nms.nbt.NBTBase value : base.asList()) {
// 1.14+
if (Version.isAfter(Version.v1_14)) {
((net.minecraft.server.v1_14_R1.NBTTagList) nmsList).add(((net.minecraft.server.v1_14_R1.NBTTagList) nmsList).size(), (net.minecraft.server.v1_14_R1.NBTBase) toNBTBase(value));
}
// 1.13
else if (Version.isAfter(Version.v1_13)) {
((net.minecraft.server.v1_13_R2.NBTTagList) nmsList).add((net.minecraft.server.v1_13_R2.NBTBase) toNBTBase(value));
}
// 1.12-
else {
((NBTTagList) nmsList).add((NBTBase) toNBTBase(value));
}
}
return nmsList;
case 10:
Object nmsTag = new net.minecraft.server.v1_8_R3.NBTTagCompound();
for (Map.Entry<String, io.izzel.taboolib.module.nms.nbt.NBTBase> entry : base.asCompound().entrySet()) {
((Map) SimpleReflection.getFieldValue(NBTTagCompound.class, nmsTag, "map")).put(entry.getKey(), toNBTBase(entry.getValue()));
}
return nmsTag;
}
return null;
}
private Object fromNBTBase(Object base) {
if (base instanceof net.minecraft.server.v1_8_R3.NBTTagCompound) {
NBTCompound nbtCompound = new NBTCompound();
for (Map.Entry<String, net.minecraft.server.v1_12_R1.NBTBase> entry : ((Map<String, net.minecraft.server.v1_12_R1.NBTBase>) SimpleReflection.getFieldValue(NBTTagCompound.class, base, "map")).entrySet()) {
nbtCompound.put(entry.getKey(), (io.izzel.taboolib.module.nms.nbt.NBTBase) fromNBTBase(entry.getValue()));
}
return nbtCompound;
} else if (base instanceof NBTTagList) {
NBTList nbtList = new NBTList();
for (Object v : (List) SimpleReflection.getFieldValue(NBTTagList.class, base, "list")) {
nbtList.add((io.izzel.taboolib.module.nms.nbt.NBTBase) fromNBTBase(v));
}
return nbtList;
} else if (base instanceof NBTTagString) {
return new io.izzel.taboolib.module.nms.nbt.NBTBase(SimpleReflection.getFieldValue(NBTTagString.class, base, "data", ""));
} else if (base instanceof NBTTagDouble) {
return new io.izzel.taboolib.module.nms.nbt.NBTBase(SimpleReflection.getFieldValue(NBTTagDouble.class, base, "data", 0D));
} else if (base instanceof NBTTagInt) {
return new io.izzel.taboolib.module.nms.nbt.NBTBase(SimpleReflection.getFieldValue(NBTTagInt.class, base, "data", 0));
} else if (base instanceof NBTTagFloat) {
return new io.izzel.taboolib.module.nms.nbt.NBTBase(SimpleReflection.getFieldValue(NBTTagFloat.class, base, "data", (float) 0));
} else if (base instanceof NBTTagShort) {
return new io.izzel.taboolib.module.nms.nbt.NBTBase(SimpleReflection.getFieldValue(NBTTagShort.class, base, "data", (short) 0));
} else if (base instanceof NBTTagLong) {
return new io.izzel.taboolib.module.nms.nbt.NBTBase(SimpleReflection.getFieldValue(NBTTagLong.class, base, "data", 0L));
} else if (base instanceof NBTTagByte) {
return new io.izzel.taboolib.module.nms.nbt.NBTBase(SimpleReflection.getFieldValue(NBTTagByte.class, base, "data", (byte) 0D));
} else if (base instanceof NBTTagIntArray) {
return new io.izzel.taboolib.module.nms.nbt.NBTBase(SimpleReflection.getFieldValue(NBTTagIntArray.class, base, "data", new int[0]));
} else if (base instanceof NBTTagByteArray) {
return new io.izzel.taboolib.module.nms.nbt.NBTBase(SimpleReflection.getFieldValue(NBTTagByteArray.class, base, "data", new byte[0]));
}
return null;
}
}

View File

@@ -0,0 +1,147 @@
package io.izzel.taboolib.module.nms.nbt;
import java.util.Arrays;
import java.util.Objects;
/**
* @Author 坏黑
* @Since 2019-05-24 17:45
*/
public class NBTBase {
protected NBTType type;
protected Object data;
public NBTBase(String data) {
this.type = NBTType.STRING;
this.data = data;
}
public NBTBase(byte data) {
this.type = NBTType.BYTE;
this.data = data;
}
public NBTBase(byte[] data) {
this.type = NBTType.BYTE_ARRAY;
this.data = data;
}
public NBTBase(int data) {
this.type = NBTType.INT;
this.data = data;
}
public NBTBase(int[] data) {
this.type = NBTType.INT_ARRAY;
this.data = data;
}
public NBTBase(double data) {
this.type = NBTType.DOUBLE;
this.data = data;
}
public NBTBase(float data) {
this.type = NBTType.FLOAT;
this.data = data;
}
public NBTBase(short data) {
this.type = NBTType.SHORT;
this.data = data;
}
public NBTBase(long data) {
this.type = NBTType.LONG;
this.data = data;
}
public NBTBase(NBTCompound data) {
this.type = NBTType.COMPOUND;
this.data = data;
}
public NBTBase(NBTList data) {
this.type = NBTType.LIST;
this.data = data;
}
public String asString() {
return (String) data;
}
public byte asByte() {
return (byte) data;
}
public byte[] asByteArray() {
return (byte[]) data;
}
public int asInt() {
return (int) data;
}
public int[] asIntArray() {
return (int[]) data;
}
public double asDouble() {
return (double) data;
}
public float asFloat() {
return (float) data;
}
public short asShort() {
return (short) data;
}
public long asLong() {
return (long) data;
}
public NBTCompound asCompound() {
return (NBTCompound) data;
}
public NBTList asList() {
return (NBTList) data;
}
public NBTType getType() {
return type;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof NBTBase)) {
return false;
}
NBTBase nbtBase = (NBTBase) o;
return getType() == nbtBase.getType() &&
Objects.equals(data, nbtBase.data);
}
@Override
public int hashCode() {
return Objects.hash(getType(), data);
}
@Override
public String toString() {
switch (type) {
case INT_ARRAY:
return Arrays.toString(asIntArray());
case BYTE_ARRAY:
return Arrays.toString(asByteArray());
default:
return String.valueOf(data);
}
}
}

View File

@@ -0,0 +1,163 @@
package io.izzel.taboolib.module.nms.nbt;
import com.google.common.collect.Maps;
import java.util.Collection;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Function;
/**
* @Author 坏黑
* @Since 2019-05-24 17:44
*/
public class NBTCompound extends NBTBase implements Map<String, NBTBase> {
private Map<String, NBTBase> value = Maps.newConcurrentMap();
public NBTCompound() {
super(0);
this.type = NBTType.COMPOUND;
this.data = this;
}
@Override
public int size() {
return value.size();
}
@Override
public boolean isEmpty() {
return value.isEmpty();
}
@Override
public boolean containsKey(Object key) {
return value.containsKey(key);
}
@Override
public boolean containsValue(Object value) {
return this.value.containsValue(value);
}
@Override
public NBTBase get(Object key) {
return value.get(key);
}
@Override
public NBTBase put(String key, NBTBase value) {
return this.value.put(key, value);
}
@Override
public NBTBase remove(Object key) {
return value.remove(key);
}
@Override
public void putAll(Map m) {
this.value.putAll(m);
}
@Override
public void clear() {
this.value.clear();
}
@Override
public Set keySet() {
return this.value.keySet();
}
@Override
public Collection values() {
return this.value.values();
}
@Override
public Set<Entry<String, NBTBase>> entrySet() {
return this.value.entrySet();
}
@Override
public NBTBase getOrDefault(Object key, NBTBase defaultValue) {
return this.value.getOrDefault(key, defaultValue);
}
@Override
public void forEach(BiConsumer<? super String, ? super NBTBase> action) {
this.value.forEach(action);
}
@Override
public void replaceAll(BiFunction<? super String, ? super NBTBase, ? extends NBTBase> function) {
this.value.replaceAll(function);
}
@Override
public NBTBase putIfAbsent(String key, NBTBase value) {
return this.value.putIfAbsent(key, value);
}
@Override
public boolean remove(Object key, Object value) {
return this.value.remove(key, value);
}
@Override
public boolean replace(String key, NBTBase oldValue, NBTBase newValue) {
return this.value.replace(key, oldValue, newValue);
}
@Override
public NBTBase replace(String key, NBTBase value) {
return this.value.replace(key, value);
}
@Override
public NBTBase computeIfAbsent(String key, Function<? super String, ? extends NBTBase> mappingFunction) {
return this.value.computeIfAbsent(key, mappingFunction);
}
@Override
public NBTBase computeIfPresent(String key, BiFunction<? super String, ? super NBTBase, ? extends NBTBase> remappingFunction) {
return this.value.computeIfPresent(key, remappingFunction);
}
@Override
public NBTBase compute(String key, BiFunction<? super String, ? super NBTBase, ? extends NBTBase> remappingFunction) {
return this.value.compute(key, remappingFunction);
}
@Override
public NBTBase merge(String key, NBTBase value, BiFunction<? super NBTBase, ? super NBTBase, ? extends NBTBase> remappingFunction) {
return this.value.merge(key, value, remappingFunction);
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof NBTCompound)) {
return false;
}
NBTCompound that = (NBTCompound) o;
return Objects.equals(value, that.value);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), value);
}
@Override
public String toString() {
return String.valueOf(value);
}
}

View File

@@ -0,0 +1,195 @@
package io.izzel.taboolib.module.nms.nbt;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.function.UnaryOperator;
import java.util.stream.Stream;
/**
* @Author 坏黑
* @Since 2019-05-24 18:37
*/
public class NBTList extends NBTBase implements List<NBTBase> {
private List<NBTBase> value = new CopyOnWriteArrayList<>();
public NBTList() {
super(0);
this.type = NBTType.LIST;
this.data = this;
}
@Override
public int size() {
return value.size();
}
@Override
public boolean isEmpty() {
return value.isEmpty();
}
@Override
public boolean contains(Object o) {
return value.contains(0);
}
@Override
public Iterator<NBTBase> iterator() {
return value.iterator();
}
@Override
public Object[] toArray() {
return value.toArray();
}
@Override
public <T> T[] toArray(T[] a) {
return value.toArray(a);
}
@Override
public boolean add(NBTBase base) {
return value.add(base);
}
@Override
public boolean remove(Object o) {
return value.remove(o);
}
@Override
public boolean containsAll(Collection<?> c) {
return value.containsAll(c);
}
@Override
public boolean addAll(Collection<? extends NBTBase> c) {
return value.addAll(c);
}
@Override
public boolean addAll(int index, Collection<? extends NBTBase> c) {
return value.addAll(index, c);
}
@Override
public boolean removeAll(Collection<?> c) {
return value.removeAll(c);
}
@Override
public boolean removeIf(Predicate<? super NBTBase> filter) {
return value.removeIf(filter);
}
@Override
public boolean retainAll(Collection<?> c) {
return value.retainAll(c);
}
@Override
public void replaceAll(UnaryOperator<NBTBase> operator) {
value.replaceAll(operator);
}
@Override
public void sort(Comparator<? super NBTBase> c) {
value.sort(c);
}
@Override
public void clear() {
value.clear();
}
@Override
public NBTBase get(int index) {
return value.get(index);
}
@Override
public NBTBase set(int index, NBTBase element) {
return value.set(index, element);
}
@Override
public void add(int index, NBTBase element) {
value.add(index, element);
}
@Override
public NBTBase remove(int index) {
return value.remove(index);
}
@Override
public int indexOf(Object o) {
return value.indexOf(o);
}
@Override
public int lastIndexOf(Object o) {
return value.lastIndexOf(o);
}
@Override
public ListIterator<NBTBase> listIterator() {
return value.listIterator();
}
@Override
public ListIterator<NBTBase> listIterator(int index) {
return value.listIterator(index);
}
@Override
public List<NBTBase> subList(int fromIndex, int toIndex) {
return value.subList(fromIndex, toIndex);
}
@Override
public Spliterator<NBTBase> spliterator() {
return value.spliterator();
}
@Override
public Stream<NBTBase> stream() {
return value.stream();
}
@Override
public Stream<NBTBase> parallelStream() {
return value.parallelStream();
}
@Override
public void forEach(Consumer<? super NBTBase> action) {
value.forEach(action);
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof NBTList)) {
return false;
}
NBTList nbtBases = (NBTList) o;
return Objects.equals(value, nbtBases.value);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), value);
}
@Override
public String toString() {
return String.valueOf(value);
}
}

View File

@@ -0,0 +1,42 @@
package io.izzel.taboolib.module.nms.nbt;
/**
* @Author 坏黑
* @Since 2019-05-24 17:46
*/
public enum NBTType {
END(0),
BYTE(1),
SHORT(2),
INT(3),
LONG(4),
FLOAT(5),
DOUBLE(6),
BYTE_ARRAY(7),
INT_ARRAY(11),
STRING(8),
LIST(9),
COMPOUND(10);
private int id;
NBTType(int i) {
this.id = i;
}
public int getId() {
return this.id;
}
}

View File

@@ -0,0 +1,73 @@
package io.izzel.taboolib.module.packet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import io.izzel.taboolib.module.packet.channel.ChannelExecutor;
import io.izzel.taboolib.module.lite.SimpleVersionControl;
import io.izzel.taboolib.module.inject.TListener;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.event.server.PluginDisableEvent;
import org.bukkit.plugin.Plugin;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Optional;
/**
* @Author 坏黑
* @Since 2018-10-28 14:52
*/
@TListener
public class TPacketHandler implements Listener {
private static Map<String, List<TPacketListener>> packetListeners = Maps.newHashMap();
private static ChannelExecutor channelExecutor;
public TPacketHandler() {
try {
channelExecutor = (ChannelExecutor) SimpleVersionControl.createNMS("io.izzel.taboolib.module.packet.channel.InternalChannelExecutor").translate().newInstance();
} catch (Exception e) {
e.printStackTrace();
}
}
@EventHandler
public void onJoin(PlayerJoinEvent e) {
channelExecutor.addPlayerChannel(e.getPlayer());
}
@EventHandler
public void onQuit(PlayerQuitEvent e) {
channelExecutor.removePlayerChannel(e.getPlayer());
}
@EventHandler
public void onDisable(PluginDisableEvent e) {
removeListener(e.getPlugin());
}
public static void sendPacket(Player player, Object packet) {
channelExecutor.sendPacket(player, packet);
}
public static void addListener(Plugin plugin, TPacketListener listener) {
packetListeners.computeIfAbsent(plugin.getName(), name -> Lists.newArrayList()).add(listener);
}
public static void removeListener(Plugin plugin) {
packetListeners.remove(plugin.getName());
}
public static void removeListener(Plugin plugin, TPacketListener listener) {
Optional.ofNullable(packetListeners.get(plugin.getName())).ifPresent(list -> list.remove(listener));
}
public static Collection<List<TPacketListener>> getListeners() {
return packetListeners.values();
}
}

View File

@@ -0,0 +1,19 @@
package io.izzel.taboolib.module.packet;
import org.bukkit.entity.Player;
/**
* @Author 坏黑
* @Since 2018-10-28 14:35
*/
public abstract class TPacketListener {
public boolean onSend(Player player, Object packet) {
return true;
}
public boolean onReceive(Player player, Object packet) {
return true;
}
}

View File

@@ -0,0 +1,74 @@
package io.izzel.taboolib.module.packet.channel;
import io.netty.channel.Channel;
import io.netty.channel.ChannelDuplexHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPromise;
import io.izzel.taboolib.module.packet.TPacketHandler;
import org.bukkit.entity.Player;
import java.util.Collection;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* @Author 坏黑
* @Since 2018-10-28 14:34
*/
public abstract class ChannelExecutor {
private ExecutorService addChannelService = Executors.newSingleThreadExecutor();
private ExecutorService removeChannelService = Executors.newSingleThreadExecutor();
public abstract void sendPacket(Player player, Object packet);
public abstract Channel getPlayerChannel(Player player);
public void addPlayerChannel(Player player) {
addChannelService.submit(() -> {
getPlayerChannel(player).pipeline().addBefore("packet_handler", "taboolib_packet_handler", new ChannelHandler(player));
});
}
public void removePlayerChannel(Player player) {
removeChannelService.submit(() -> {
Channel playerChannel = getPlayerChannel(player);
if (playerChannel.pipeline().get("taboolib_packet_handler") != null) {
playerChannel.pipeline().remove("taboolib_packet_handler");
}
});
}
class ChannelHandler extends ChannelDuplexHandler {
private Player player;
public ChannelHandler(Player player) {
this.player = player;
}
@Override
public void write(ChannelHandlerContext channelHandlerContext, Object o, ChannelPromise channelPromise) throws Exception {
try {
if (TPacketHandler.getListeners().stream().flatMap(Collection::stream).anyMatch(packetListener -> !packetListener.onSend(player, o))) {
return;
}
} catch (Exception e) {
e.printStackTrace();
}
super.write(channelHandlerContext, o, channelPromise);
}
@Override
public void channelRead(ChannelHandlerContext channelHandlerContext, Object o) throws Exception {
try {
if (TPacketHandler.getListeners().stream().flatMap(Collection::stream).anyMatch(packetListener -> !packetListener.onReceive(player, o))) {
return;
}
} catch (Exception e) {
e.printStackTrace();
}
super.channelRead(channelHandlerContext, o);
}
}
}

View File

@@ -0,0 +1,28 @@
package io.izzel.taboolib.module.packet.channel;
import io.izzel.taboolib.module.logger.TLogger;
import io.netty.channel.Channel;
import net.minecraft.server.v1_8_R3.Packet;
import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer;
import org.bukkit.entity.Player;
/**
* @Author 坏黑
* @Since 2018-10-28 15:12
*/
public class InternalChannelExecutor extends ChannelExecutor {
@Override
public void sendPacket(Player player, Object packet) {
if (packet instanceof Packet) {
((CraftPlayer) player).getHandle().playerConnection.sendPacket((Packet) packet);
} else {
TLogger.getGlobalLogger().warn("Invalid packet: " + packet.getClass().getName());
}
}
@Override
public Channel getPlayerChannel(Player player) {
return ((CraftPlayer) player).getHandle().playerConnection.networkManager.channel;
}
}

View File

@@ -0,0 +1,18 @@
package io.izzel.taboolib.module.serialize;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @Author sky
* @Since 2018-10-05 12:11
*
* 用于标注不需要进行序列化的内容
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DoNotSerialize {
}

View File

@@ -0,0 +1,34 @@
package io.izzel.taboolib.module.serialize;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
/**
* @Author 坏黑
* @Since 2019-03-08 17:28
*/
public interface TSerializable {
default void read(String fieldName, String value) {
}
default String write(String fieldName, Object value) {
return null;
}
default Object read(String value) {
return TSerializer.read(this, value);
}
default String write() {
return TSerializer.write(this);
}
default Object readBase64(String value) {
return TSerializer.read(this, new String(Base64.getDecoder().decode(value), StandardCharsets.UTF_8));
}
default String writeBase64() {
return Base64.getEncoder().encodeToString(TSerializer.write(this).getBytes(StandardCharsets.UTF_8));
}
}

View File

@@ -0,0 +1,18 @@
package io.izzel.taboolib.module.serialize;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @Author sky
* @Since 2018-10-05 12:11
*
* 用于标识 Collection 类型的字段
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TSerializeCollection {
}

View File

@@ -0,0 +1,18 @@
package io.izzel.taboolib.module.serialize;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @Author sky
* @Since 2018-10-05 12:11
*
* 用于标识 TSerializable 类型的字段
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TSerializeCustom {
}

View File

@@ -0,0 +1,18 @@
package io.izzel.taboolib.module.serialize;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @Author sky
* @Since 2018-10-05 12:11
*
* 用于标识 Map 类型的字段
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TSerializeMap {
}

View File

@@ -0,0 +1,267 @@
package io.izzel.taboolib.module.serialize;
import com.google.common.collect.Maps;
import com.google.gson.*;
import io.izzel.taboolib.module.lite.SimpleReflection;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.configuration.serialization.ConfigurationSerializable;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.Collection;
import java.util.Map;
import java.util.Optional;
/**
* @Author 坏黑
* @Since 2019-03-08 17:31
*/
public class TSerializer {
private static Map<String, TSerializerElement> generated = Maps.newHashMap();
public static TSerializable read(TSerializable serializable, String serializedString) {
SimpleReflection.checkAndSave(serializable.getClass());
try {
JsonObject jsonObject = (JsonObject) new JsonParser().parse(serializedString);
if (jsonObject.has("serializeObject")) {
JsonObject serializeObject = jsonObject.getAsJsonObject("serializeObject");
for (Map.Entry<String, JsonElement> jsonElementEntry : serializeObject.entrySet()) {
try {
Field declaredField = SimpleReflection.getField(serializable.getClass(), jsonElementEntry.getKey());
if (declaredField.isAnnotationPresent(DoNotSerialize.class)) {
continue;
}
// Serializable
if (declaredField.isAnnotationPresent(TSerializeCustom.class) && TSerializable.class.isAssignableFrom(declaredField.getType())) {
declaredField.set(serializable, generateElement((Class<? extends TSerializable>) declaredField.getType()).read(jsonElementEntry.getValue().getAsString()));
}
// List
else if (declaredField.isAnnotationPresent(TSerializeCollection.class) && Collection.class.isAssignableFrom(declaredField.getType())) {
Class listType = SimpleReflection.getListType(declaredField);
if (listType == null) {
serializable.read(jsonElementEntry.getKey(), jsonElementEntry.getValue().getAsString());
continue;
}
TSerializerElementGeneral serializer = Arrays.stream(TSerializerElementGeneral.values()).filter(serializerElements -> serializerElements.getSerializer().matches(listType)).findFirst().orElse(null);
if (serializer == null) {
serializable.read(jsonElementEntry.getKey(), jsonElementEntry.getValue().getAsString());
} else {
readCollection((Collection) declaredField.get(serializable), jsonElementEntry.getValue().getAsString(), checkCustom(listType, serializer));
}
}
// Map
else if (declaredField.isAnnotationPresent(TSerializeMap.class) && Map.class.isAssignableFrom(declaredField.getType())) {
Class[] mapType = SimpleReflection.getMapType(declaredField);
if (mapType == null) {
serializable.read(jsonElementEntry.getKey(), jsonElementEntry.getValue().getAsString());
continue;
}
TSerializerElementGeneral serializerK = Arrays.stream(TSerializerElementGeneral.values()).filter(serializerElements -> serializerElements.getSerializer().matches(mapType[0])).findFirst().orElse(null);
TSerializerElementGeneral serializerV = Arrays.stream(TSerializerElementGeneral.values()).filter(serializerElements -> serializerElements.getSerializer().matches(mapType[1])).findFirst().orElse(null);
if (serializerK == null || serializerV == null) {
serializable.read(jsonElementEntry.getKey(), jsonElementEntry.getValue().getAsString());
} else {
readMap((Map) declaredField.get(serializable), jsonElementEntry.getValue().getAsString(), checkCustom(mapType[0], serializerK), checkCustom(mapType[1], serializerV));
}
}
// 未声明类型
else {
TSerializerElementGeneral serializer = Arrays.stream(TSerializerElementGeneral.values()).filter(serializerElements -> serializerElements.getSerializer().matches(declaredField.getType())).findFirst().orElse(null);
if (serializer == null) {
serializable.read(jsonElementEntry.getKey(), jsonElementEntry.getValue().getAsString());
} else {
declaredField.set(serializable, serializer.getSerializer().read(jsonElementEntry.getValue().getAsString()));
}
}
} catch (Throwable t) {
t.printStackTrace();
}
}
}
} catch (Throwable t) {
t.printStackTrace();
}
return serializable;
}
public static String write(TSerializable serializable) {
SimpleReflection.checkAndSave(serializable.getClass());
JsonObject jsonObject = new JsonObject();
JsonObject serializeObject = new JsonObject();
for (Field declaredField : SimpleReflection.getFields(serializable.getClass()).values()) {
try {
if (!declaredField.isAnnotationPresent(DoNotSerialize.class) && !Modifier.isStatic(declaredField.getModifiers())) {
Object fieldObject = declaredField.get(serializable);
if (fieldObject == null) {
continue;
}
// Serializable
if (declaredField.isAnnotationPresent(TSerializeCustom.class) && TSerializable.class.isAssignableFrom(declaredField.getType())) {
serializeObject.addProperty(declaredField.getName(), generateElement((Class<? extends TSerializable>) declaredField.getType()).write(fieldObject));
}
// List
else if (declaredField.isAnnotationPresent(TSerializeCollection.class) && Collection.class.isAssignableFrom(declaredField.getType())) {
Class listType = SimpleReflection.getListType(declaredField);
if (listType == null) {
Optional.ofNullable(serializable.write(declaredField.getName(), fieldObject)).ifPresent(value -> serializeObject.addProperty(declaredField.getName(), value));
continue;
}
TSerializerElementGeneral serializer = Arrays.stream(TSerializerElementGeneral.values()).filter(serializerElements -> serializerElements.getSerializer().matches(listType)).findFirst().orElse(null);
if (serializer == null) {
Optional.ofNullable(serializable.write(declaredField.getName(), fieldObject)).ifPresent(value -> serializeObject.addProperty(declaredField.getName(), value));
} else {
serializeObject.addProperty(declaredField.getName(), writeCollection((Collection) fieldObject, checkCustom(listType, serializer)));
}
}
// Map
else if (declaredField.isAnnotationPresent(TSerializeMap.class) && Map.class.isAssignableFrom(declaredField.getType())) {
Class[] mapType = SimpleReflection.getMapType(declaredField);
if (mapType == null) {
Optional.ofNullable(serializable.write(declaredField.getName(), fieldObject)).ifPresent(value -> serializeObject.addProperty(declaredField.getName(), value));
continue;
}
TSerializerElementGeneral serializerK = Arrays.stream(TSerializerElementGeneral.values()).filter(serializerElements -> serializerElements.getSerializer().matches(mapType[0])).findFirst().orElse(null);
TSerializerElementGeneral serializerV = Arrays.stream(TSerializerElementGeneral.values()).filter(serializerElements -> serializerElements.getSerializer().matches(mapType[1])).findFirst().orElse(null);
if (serializerK == null || serializerV == null) {
Optional.ofNullable(serializable.write(declaredField.getName(), fieldObject)).ifPresent(value -> serializeObject.addProperty(declaredField.getName(), value));
} else {
serializeObject.addProperty(declaredField.getName(), writeMap((Map) fieldObject, checkCustom(mapType[0], serializerK), checkCustom(mapType[1], serializerV)));
}
}
// 未声明类型
else {
TSerializerElementGeneral serializer = Arrays.stream(TSerializerElementGeneral.values()).filter(serializerElements -> serializerElements.getSerializer().matches(declaredField.getType())).findFirst().orElse(null);
if (serializer == null) {
Optional.ofNullable(serializable.write(declaredField.getName(), fieldObject)).ifPresent(value -> serializeObject.addProperty(declaredField.getName(), value));
} else {
serializeObject.addProperty(declaredField.getName(), serializer.getSerializer().write(fieldObject));
}
}
}
} catch (Throwable t) {
t.printStackTrace();
}
}
jsonObject.add("serializeObject", serializeObject);
return jsonObject.toString();
}
public static void readMap(Map map, String serializedString, TSerializerElementGeneral elementKey, TSerializerElementGeneral elementValue) {
readMap(map, serializedString, elementKey.getSerializer(), elementValue.getSerializer());
}
public static void readMap(Map map, String serializedString, TSerializerElement elementKey, TSerializerElement elementValue) {
try {
JsonObject jsonObject = (JsonObject) new JsonParser().parse(serializedString);
for (Map.Entry<String, JsonElement> jsonElementEntry : jsonObject.entrySet()) {
try {
map.put(elementKey.read(jsonElementEntry.getKey()), elementValue.read(jsonElementEntry.getValue().getAsString()));
} catch (Throwable t) {
t.printStackTrace();
}
}
} catch (Throwable t) {
t.printStackTrace();
}
}
public static String writeMap(Map<?, ?> map, TSerializerElementGeneral elementKey, TSerializerElementGeneral elementValue) {
return writeMap(map, elementKey.getSerializer(), elementValue.getSerializer());
}
public static String writeMap(Map<?, ?> map, TSerializerElement elementKey, TSerializerElement elementValue) {
JsonObject jsonObject = new JsonObject();
for (Map.Entry<?, ?> entry : map.entrySet()) {
try {
jsonObject.addProperty(elementKey.write(entry.getKey()), elementValue.write(entry.getValue()));
} catch (Throwable t) {
t.printStackTrace();
}
}
return jsonObject.toString();
}
public static void readCollection(Collection collection, String serializedString, TSerializerElementGeneral elementValue) {
readCollection(collection, serializedString, elementValue.getSerializer());
}
public static void readCollection(Collection collection, String serializedString, TSerializerElement elementValue) {
try {
JsonArray jsonArray = (JsonArray) new JsonParser().parse(serializedString);
for (JsonElement jsonElement : jsonArray) {
try {
collection.add(elementValue.read(jsonElement.getAsString()));
} catch (Throwable t) {
t.printStackTrace();
}
}
} catch (Throwable t) {
t.printStackTrace();
}
}
public static String writeCollection(Collection collection, TSerializerElementGeneral elementValue) {
return writeCollection(collection, elementValue.getSerializer());
}
public static String writeCollection(Collection collection, TSerializerElement elementValue) {
JsonArray jsonArray = new JsonArray();
for (Object object : collection) {
try {
jsonArray.add(new JsonPrimitive(elementValue.write(object)));
} catch (Throwable t) {
t.printStackTrace();
}
}
return jsonArray.toString();
}
public static String serializeCS(ConfigurationSerializable o) {
YamlConfiguration y = new YamlConfiguration();
y.set("value", o);
return y.saveToString();
}
public static <T extends ConfigurationSerializable> T deserializeCS(String s, Class<T> c) {
YamlConfiguration y = new YamlConfiguration();
try {
y.loadFromString(s);
} catch (InvalidConfigurationException var4) {
return null;
}
Object o = y.get("value");
return !c.isInstance(o) ? null : (T) o;
}
public static TSerializerElement generateElement(Class<? extends TSerializable> serializable) {
return generated.computeIfAbsent(serializable.getName(), n -> new TSerializerElement() {
@Override
public Object read(String value) {
try {
return serializable.newInstance().read(value);
} catch (Throwable t) {
t.printStackTrace();
}
return null;
}
@Override
public String write(Object value) {
return ((TSerializable) value).write();
}
@Override
public boolean matches(Class objectClass) {
return true;
}
});
}
private static TSerializerElement checkCustom(Class type, TSerializerElementGeneral serializer) {
return serializer == TSerializerElementGeneral.CUSTOM ? generateElement(type) : serializer.getSerializer();
}
}

View File

@@ -0,0 +1,14 @@
package io.izzel.taboolib.module.serialize;
/**
* @Author 坏黑
* @Since 2019-03-08 17:28
*/
public interface TSerializerElement<T> {
T read(String value);
String write(T value);
boolean matches(Class objectClass);
}

View File

@@ -0,0 +1,234 @@
package io.izzel.taboolib.module.serialize;
import io.izzel.taboolib.origin.lite.Numbers;
import org.bukkit.Location;
import org.bukkit.inventory.ItemStack;
import java.util.Objects;
/**
* @Author 坏黑
* @Since 2019-03-10 18:49
*/
public enum TSerializerElementGeneral {
STRING(new TSerializerElement() {
@Override
public String read(String value) {
return String.valueOf(value);
}
@Override
public String write(Object value) {
return Objects.toString(value);
}
@Override
public boolean matches(Class objectClass) {
return String.class.equals(objectClass);
}
}),
INT(new TSerializerElement() {
@Override
public Integer read(String value) {
try {
return Integer.parseInt(value);
} catch (Throwable t) {
t.printStackTrace();
}
return 0;
}
@Override
public String write(Object value) {
return Objects.toString(value);
}
@Override
public boolean matches(Class objectClass) {
return Integer.class.equals(objectClass) || Integer.TYPE.equals(objectClass);
}
}),
LONG(new TSerializerElement() {
@Override
public Long read(String value) {
try {
return Long.parseLong(value);
} catch (Throwable t) {
t.printStackTrace();
}
return 0L;
}
@Override
public String write(Object value) {
return Objects.toString(value);
}
@Override
public boolean matches(Class objectClass) {
return Long.class.equals(objectClass) || Long.TYPE.equals(objectClass);
}
}),
SHORT(new TSerializerElement() {
@Override
public Short read(String value) {
try {
return Short.parseShort(value);
} catch (Throwable t) {
t.printStackTrace();
}
return (short) 0;
}
@Override
public String write(Object value) {
return Objects.toString(value);
}
@Override
public boolean matches(Class objectClass) {
return Short.class.equals(objectClass) || Short.TYPE.equals(objectClass);
}
}),
DOUBLE(new TSerializerElement() {
@Override
public Double read(String value) {
try {
return Double.parseDouble(value);
} catch (Throwable t) {
t.printStackTrace();
}
return 0D;
}
@Override
public String write(Object value) {
return Objects.toString(value);
}
@Override
public boolean matches(Class objectClass) {
return Double.class.equals(objectClass) || Boolean.TYPE.equals(objectClass);
}
}),
FLOAT(new TSerializerElement() {
@Override
public Float read(String value) {
try {
return Float.parseFloat(value);
} catch (Throwable t) {
t.printStackTrace();
}
return 0f;
}
@Override
public String write(Object value) {
return Objects.toString(value);
}
@Override
public boolean matches(Class objectClass) {
return Float.class.equals(objectClass) || Float.TYPE.equals(objectClass);
}
}),
BOOLEAN(new TSerializerElement() {
@Override
public Boolean read(String value) {
try {
return Numbers.getBoolean(value);
} catch (Throwable t) {
t.printStackTrace();
}
return false;
}
@Override
public String write(Object value) {
return Objects.toString(value);
}
@Override
public boolean matches(Class objectClass) {
return Boolean.class.equals(objectClass) || Boolean.TYPE.equals(objectClass);
}
}),
ITEM_STACK(new TSerializerElement() {
@Override
public ItemStack read(String value) {
return TSerializer.deserializeCS(value, ItemStack.class);
}
@Override
public String write(Object value) {
return TSerializer.serializeCS((ItemStack) value);
}
@Override
public boolean matches(Class objectClass) {
return ItemStack.class.isAssignableFrom(objectClass);
}
}),
LOCATION(new TSerializerElement() {
@Override
public Location read(String value) {
return TSerializer.deserializeCS(value, Location.class);
}
@Override
public String write(Object value) {
return TSerializer.serializeCS((Location) value);
}
@Override
public boolean matches(Class objectClass) {
return Location.class.isAssignableFrom(objectClass);
}
}),
CUSTOM(new TSerializerElement() {
@Override
public Object read(String value) {
return null;
}
@Override
public String write(Object value) {
return null;
}
@Override
public boolean matches(Class objectClass) {
return TSerializable.class.isAssignableFrom(objectClass);
}
});
private TSerializerElement serializer;
TSerializerElementGeneral(TSerializerElement serializer) {
this.serializer = serializer;
}
public TSerializerElement getSerializer() {
return serializer;
}
}

View File

@@ -0,0 +1,75 @@
package io.izzel.taboolib.module.serialize;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import io.izzel.taboolib.util.ArrayUtil;
import java.util.List;
import java.util.Map;
/**
* @Author 坏黑
* @Since 2019-04-01 17:49
*/
public class TSerializerExample {
public static void main(String[] args) {
// 创建对象
SimpleData data = new SimpleData();
// 修改参数
data.number = 9999;
data.list.addAll(ArrayUtil.asList(111D, 222D));
data.map.putAll(ImmutableMap.of("a", "b", "c", "d"));
// 序列化
String value = data.write();
// 打印
System.out.println(value);
// 创建新的对象
SimpleData dataCopy = new SimpleData();
// 反序列化
dataCopy.read(value);
// 打印
System.out.println(dataCopy);
}
/**
* 创建序列化类
* 实现 TSerializable 接口
*/
public static class SimpleData implements TSerializable {
/**
* 基本类型不需要手动进行序列化
* 包含: String、int、short、long、double、float、boolean、ItemStack、Location
*/
private String text = "123";
private int number = 100;
/**
* 包含基本类型的容器需要通过标注来完成序列化
*/
@TSerializeCollection
private List<Double> list = Lists.newArrayList();
@TSerializeMap
private Map<String, String> map = Maps.newHashMap();
/**
* 跳过序列化
*/
@DoNotSerialize
private String ignoreSerialize = "aaa";
@Override
public String toString() {
return "SimpleData{" +
"text='" + text + '\'' +
", number=" + number +
", list=" + list +
", map=" + map +
", ignoreSerialize='" + ignoreSerialize + '\'' +
'}';
}
}
}

View File

@@ -0,0 +1,46 @@
package io.izzel.taboolib.module.tellraw;
import io.izzel.taboolib.module.inject.TFunction;
import io.izzel.taboolib.module.lite.SimpleVersionControl;
import io.izzel.taboolib.module.tellraw.internal.AbstractTellraw;
import org.bukkit.Bukkit;
/**
* @Author 坏黑
* @Since 2018-11-07 22:58
*/
@TFunction(enable = "init")
public class TellrawCreator {
private static AbstractTellraw abstractTellraw;
private static boolean viaVersionLoaded;
private static boolean protocolSupportLoaded;
public static void init() {
viaVersionLoaded = Bukkit.getPluginManager().getPlugin("ViaVersion") != null;
protocolSupportLoaded = Bukkit.getPluginManager().getPlugin("ProtocolSupport") != null;
try {
abstractTellraw = (AbstractTellraw) SimpleVersionControl.createNMS("io.izzel.taboolib.module.tellraw.internal.InternalTellraw").translate().newInstance();
} catch (Exception e) {
e.printStackTrace();
}
}
// *********************************
//
// Getter and Setter
//
// *********************************
public static AbstractTellraw getAbstractTellraw() {
return abstractTellraw;
}
public static boolean isViaVersionLoaded() {
return viaVersionLoaded;
}
public static boolean isProtocolSupportLoaded() {
return protocolSupportLoaded;
}
}

View File

@@ -0,0 +1,218 @@
package io.izzel.taboolib.module.tellraw;
import io.izzel.taboolib.locale.TLocale;
import io.izzel.taboolib.util.ArrayUtil;
import io.izzel.taboolib.util.Strings;
import io.izzel.taboolib.util.chat.*;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import protocolsupport.api.ProtocolSupportAPI;
import us.myles.ViaVersion.api.Via;
import java.util.*;
import java.util.stream.Collectors;
/**
* @Author sky
* @Since 2018-05-26 14:42json
* @BuilderLevel 1.2
*/
public class TellrawJson {
private List<BaseComponent> components = new ArrayList<>();
private List<BaseComponent> componentsLatest = new ArrayList<>();
private Map<String, String[]> itemTag = new HashMap<>();
private List<String> nbtWhitelist = ArrayUtil.asList(
// 附魔
"ench",
// 附魔书
"StoredEnchantments",
// 展示
"display",
// 属性
"AttributeModifiers",
// 药水
"Potion",
// 特殊药水
"CustomPotionEffects",
// 隐藏标签
"HideFlags",
// 方块标签
"BlockEntityTag"
);
TellrawJson() {
}
public static TellrawJson create() {
return new TellrawJson();
}
public void broadcast() {
Bukkit.getOnlinePlayers().forEach(player -> send(player, new String[0]));
}
public void broadcast(String... args) {
Bukkit.getOnlinePlayers().forEach(player -> send(player, args));
}
public void send(CommandSender sender) {
send(sender, new String[0]);
}
public void send(CommandSender sender, String... args) {
if (sender instanceof Player) {
TLocale.Tellraw.send(sender, Strings.replaceWithOrder(toRawMessage((Player) sender), args));
} else {
TLocale.Tellraw.send(sender, Strings.replaceWithOrder(toRawMessage(), args));
}
}
public String toRawMessage() {
return ComponentSerializer.toString(getComponentsAll());
}
public String toRawMessage(TellrawVersion version) {
String rawMessage = toRawMessage();
if (version == TellrawVersion.CURRENT_VERSION) {
return rawMessage;
}
for (Map.Entry<String, String[]> stringEntry : itemTag.entrySet()) {
rawMessage = rawMessage.replace(stringEntry.getKey(), version == TellrawVersion.HIGH_VERSION ? stringEntry.getValue()[1] : stringEntry.getValue()[0]);
}
return rawMessage;
}
public String toRawMessage(Player player) {
// ViaVersion support!
if (TellrawCreator.isViaVersionLoaded()) {
return toRawMessage(Via.getAPI().getPlayerVersion(player) > 316 ? TellrawVersion.HIGH_VERSION : TellrawVersion.LOW_VERSION);
}
// ProtocolSupport support!
else if (TellrawCreator.isProtocolSupportLoaded()) {
return toRawMessage(ProtocolSupportAPI.getProtocolVersion(player).getId() > 316 ? TellrawVersion.HIGH_VERSION : TellrawVersion.LOW_VERSION);
}
return toRawMessage();
}
public String toLegacyText() {
return TextComponent.toLegacyText(getComponentsAll());
}
public TellrawJson newLine() {
return append("\n");
}
public TellrawJson append(String text) {
appendComponents();
componentsLatest.addAll(Arrays.asList(TextComponent.fromLegacyText(text)));
return this;
}
public TellrawJson append(TellrawJson json) {
appendComponents();
componentsLatest.addAll(Arrays.asList(json.getComponentsAll()));
itemTag.putAll(json.itemTag);
return this;
}
public TellrawJson hoverText(String text) {
getLatestComponent().forEach(component -> component.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ComponentBuilder(text).create())));
return this;
}
public TellrawJson hoverItem(ItemStack itemStack) {
return hoverItem(itemStack, true);
}
public TellrawJson hoverItem(ItemStack itemStack, boolean supportVersion) {
itemStack = TellrawCreator.getAbstractTellraw().optimizeNBT(itemStack, nbtWhitelist);
BaseComponent[] itemComponentCurrentVersion = new ComponentBuilder(TellrawCreator.getAbstractTellraw().getItemComponent(itemStack, TellrawVersion.CURRENT_VERSION)).create();
getLatestComponent().forEach(component -> component.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_ITEM, itemComponentCurrentVersion)));
if (supportVersion) {
itemTag.put(ComponentSerializer.toString(itemComponentCurrentVersion), new String[] {
ComponentSerializer.toString(new ComponentBuilder(TellrawCreator.getAbstractTellraw().getItemComponent(itemStack, TellrawVersion.LOW_VERSION)).create()),
ComponentSerializer.toString(new ComponentBuilder(TellrawCreator.getAbstractTellraw().getItemComponent(itemStack, TellrawVersion.HIGH_VERSION)).create())
});
}
return this;
}
public TellrawJson clickCommand(String command) {
getLatestComponent().forEach(component -> component.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, command)));
return this;
}
public TellrawJson clickSuggest(String command) {
getLatestComponent().forEach(component -> component.setClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, command)));
return this;
}
public TellrawJson clickOpenURL(String url) {
getLatestComponent().forEach(component -> component.setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, url)));
return this;
}
public TellrawJson clickChangePage(int page) {
getLatestComponent().forEach(component -> component.setClickEvent(new ClickEvent(ClickEvent.Action.CHANGE_PAGE, String.valueOf(page))));
return this;
}
public BaseComponent[] getComponentsAll() {
List<BaseComponent> components = this.components.stream().filter(component -> !(component instanceof TextComponent) || !((TextComponent) component).getText().isEmpty()).collect(Collectors.toList());
this.componentsLatest.stream().filter(component -> !(component instanceof TextComponent) || !((TextComponent) component).getText().isEmpty()).forEach(components::add);
return components.toArray(new BaseComponent[0]);
}
@Deprecated
public String getItemComponent(ItemStack item) {
return TellrawCreator.getAbstractTellraw().getItemComponent(item);
}
// *********************************
//
// Private Methods
//
// *********************************
private List<BaseComponent> getLatestComponent() {
return componentsLatest;
}
private void setLatestComponent(BaseComponent... component) {
componentsLatest.addAll(Arrays.asList(component));
}
private void appendComponents() {
components.addAll(componentsLatest);
componentsLatest.clear();
}
// *********************************
//
// Getter and Setter
//
// *********************************
public void setComponents(BaseComponent[] components) {
this.components = Arrays.asList(components);
}
public BaseComponent[] getComponents() {
return components.toArray(new BaseComponent[0]);
}
public List<BaseComponent> getComponentsLatest() {
return componentsLatest;
}
public Map<String, String[]> getItemTag() {
return itemTag;
}
public List<String> getNBTWhitelist() {
return nbtWhitelist;
}
}

Some files were not shown because too many files have changed in this diff Show More