├── icon.png ├── src ├── main │ ├── java │ │ └── me │ │ │ └── dpohvar │ │ │ └── powernbt │ │ │ ├── nbt │ │ │ ├── package-info.java │ │ │ ├── NBTContainerFileGZipCustom.java │ │ │ ├── NBTContainerChunk.java │ │ │ ├── NBTContainerValue.java │ │ │ ├── NBTContainerItem.java │ │ │ ├── NBTContainerFileGZip.java │ │ │ ├── NBTContainerVariable.java │ │ │ ├── NBTContainerEntity.java │ │ │ ├── NBTContainerBlock.java │ │ │ ├── NBTContainerFile.java │ │ │ ├── NBTContainerComplex.java │ │ │ └── NBTContainer.java │ │ │ ├── command │ │ │ ├── action │ │ │ │ ├── Action.java │ │ │ │ ├── ActionBitAnd.java │ │ │ │ ├── ActionBitOr.java │ │ │ │ ├── ActionBitXor.java │ │ │ │ ├── ActionCancel.java │ │ │ │ ├── ActionCopy.java │ │ │ │ ├── ActionCut.java │ │ │ │ ├── ActionDebug.java │ │ │ │ ├── ActionRemove.java │ │ │ │ ├── ActionEdit.java │ │ │ │ ├── ActionBitInverse.java │ │ │ │ ├── ActionMove.java │ │ │ │ ├── ActionEditLast.java │ │ │ │ ├── ActionMoveLast.java │ │ │ │ ├── ActionSwap.java │ │ │ │ ├── ActionRename.java │ │ │ │ ├── ActionSet.java │ │ │ │ ├── ActionBiLong.java │ │ │ │ ├── ActionView.java │ │ │ │ ├── ActionMultiply.java │ │ │ │ ├── ActionInsert.java │ │ │ │ ├── ActionSpawn.java │ │ │ │ └── ActionAddAll.java │ │ │ └── Command.java │ │ │ ├── exception │ │ │ ├── PrintTextException.java │ │ │ ├── NBTTagNotFound.java │ │ │ ├── NBTReadException.java │ │ │ ├── NBTTagUnexpectedType.java │ │ │ ├── NBTQueryException.java │ │ │ ├── NBTConvertException.java │ │ │ ├── ParseException.java │ │ │ └── SourceException.java │ │ │ ├── utils │ │ │ ├── viewer │ │ │ │ ├── components │ │ │ │ │ ├── Element.java │ │ │ │ │ ├── InteractiveElement.java │ │ │ │ │ ├── ButtonEdit.java │ │ │ │ │ ├── ButtonSelectJson.java │ │ │ │ │ ├── ButtonCopyToBuffer.java │ │ │ │ │ ├── ButtonPasteFromBuffer.java │ │ │ │ │ ├── ButtonCopyToClipboard.java │ │ │ │ │ ├── ButtonUpdate.java │ │ │ │ │ ├── ButtonRemove.java │ │ │ │ │ ├── ListElement.java │ │ │ │ │ ├── NavbarElement.java │ │ │ │ │ ├── MapElement.java │ │ │ │ │ └── FooterElement.java │ │ │ │ ├── EventBuilder.java │ │ │ │ ├── ContainerControl.java │ │ │ │ ├── InteractiveViewer.java │ │ │ │ ├── ViewerStyle.java │ │ │ │ └── DisplayValueHelper.java │ │ │ ├── query │ │ │ │ ├── FreeIndexSelector.java │ │ │ │ ├── IndexSelector.java │ │ │ │ ├── QSelector.java │ │ │ │ ├── StringAsJsonSelector.java │ │ │ │ ├── KeySelector.java │ │ │ │ ├── IntegerSelector.java │ │ │ │ └── RangeSelector.java │ │ │ ├── SimpleListener.java │ │ │ ├── PowerJSONParser.java │ │ │ ├── Translator.java │ │ │ ├── Caller.java │ │ │ └── StringParser.java │ │ │ ├── api │ │ │ ├── NBTBox.java │ │ │ └── NBTBridge.java │ │ │ ├── extension │ │ │ ├── nbt │ │ │ │ └── NBTCompoundProperties.java │ │ │ └── NBTExtension.java │ │ │ ├── listener │ │ │ └── SelectListener.java │ │ │ ├── completer │ │ │ ├── TypeCompleter.java │ │ │ └── Completer.java │ │ │ └── PowerNBT.java │ └── resources │ │ ├── META-INF │ │ └── groovy │ │ │ └── org.codehaus.groovy.runtime.ExtensionModule │ │ ├── plugin.yml │ │ ├── en.yml │ │ ├── config.yml │ │ └── ru.yml └── test │ └── java │ └── me │ └── dpohvar │ └── powernbt │ └── BasicTest.java ├── .gitignore ├── scripts ├── jitpack_build.sh └── jitpack_prepare.sh ├── jitpack.yml ├── .github └── workflows │ ├── maven-publish.yml │ └── create-gh-release.yml ├── LICENSE └── pom.xml /icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flinbein/PowerNBT/HEAD/icon.png -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/nbt/package-info.java: -------------------------------------------------------------------------------- 1 | @Deprecated 2 | package me.dpohvar.powernbt.nbt; -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | *.jar 3 | PowerNBT.iml 4 | target 5 | out 6 | doc 7 | .classpath 8 | .settings/ 9 | .project 10 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/groovy/org.codehaus.groovy.runtime.ExtensionModule: -------------------------------------------------------------------------------- 1 | moduleName=powernbt-ext 2 | moduleVersion=${plugin-version} 3 | extensionClasses=me.dpohvar.powernbt.extension.NBTExtension -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/command/action/Action.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.command.action; 2 | 3 | public abstract class Action { 4 | 5 | abstract public void execute() throws Exception; 6 | 7 | } 8 | -------------------------------------------------------------------------------- /scripts/jitpack_build.sh: -------------------------------------------------------------------------------- 1 | export PLUGIN_VERSION=`cat ./PLUGIN_VERSION.var` 2 | echo "build plugin-version=$PLUGIN_VERSION" 3 | env PLUGIN_VERSION="$PLUGIN_VERSION" mvn -Dplugin-version=$PLUGIN_VERSION clean install -DskipTests -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/exception/PrintTextException.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.exception; 2 | 3 | public class PrintTextException extends RuntimeException { 4 | public PrintTextException(String s){ 5 | super(s); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/utils/viewer/components/Element.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.utils.viewer.components; 2 | 3 | import net.md_5.bungee.api.chat.BaseComponent; 4 | 5 | public interface Element { 6 | public BaseComponent getComponent(); 7 | } 8 | -------------------------------------------------------------------------------- /jitpack.yml: -------------------------------------------------------------------------------- 1 | before_install: 2 | - chmod 770 ./scripts/jitpack_prepare.sh 3 | - ./scripts/jitpack_prepare.sh 4 | - sdk install java 17.0.2-open 5 | - sdk use java 17.0.2-open 6 | install: 7 | - chmod 770 ./scripts/jitpack_build.sh 8 | - ./scripts/jitpack_build.sh 9 | -------------------------------------------------------------------------------- /scripts/jitpack_prepare.sh: -------------------------------------------------------------------------------- 1 | if [[ $VERSION =~ ^v[0-9.]*$ ]] 2 | then 3 | echo "${VERSION:1}" > PLUGIN_VERSION.var 4 | elif [[ $VERSION =~ ^[0-9.]*$ ]] 5 | then 6 | echo "${VERSION}" > PLUGIN_VERSION.var 7 | elif [[ $VERSION =~ -SNAPSHOT$ ]] 8 | then 9 | echo "${VERSION}" > PLUGIN_VERSION.var 10 | else 11 | echo "${VERSION}-SNAPSHOT" > PLUGIN_VERSION.var 12 | fi 13 | echo "save PLUGIN_VERSION.var = `cat ./PLUGIN_VERSION.var`" -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/command/action/ActionBitAnd.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.command.action; 2 | 3 | import me.dpohvar.powernbt.utils.Caller; 4 | 5 | public class ActionBitAnd extends ActionBiLong { 6 | 7 | public ActionBitAnd(Caller caller, String o1, String q1, String o2, String q2) { 8 | super(caller, o1, q1, o2, q2); 9 | } 10 | 11 | @Override 12 | long operation(long arg1, long arg2) { 13 | return arg1 & arg2; 14 | } 15 | } -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/command/action/ActionBitOr.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.command.action; 2 | 3 | import me.dpohvar.powernbt.utils.Caller; 4 | 5 | public class ActionBitOr extends ActionBiLong { 6 | 7 | public ActionBitOr(Caller caller, String o1, String q1, String o2, String q2) { 8 | super(caller, o1, q1, o2, q2); 9 | } 10 | 11 | @Override 12 | long operation(long arg1, long arg2) { 13 | return arg1 | arg2; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/command/action/ActionBitXor.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.command.action; 2 | 3 | import me.dpohvar.powernbt.utils.Caller; 4 | 5 | public class ActionBitXor extends ActionBiLong { 6 | 7 | public ActionBitXor(Caller caller, String o1, String q1, String o2, String q2) { 8 | super(caller, o1, q1, o2, q2); 9 | } 10 | 11 | @Override 12 | long operation(long arg1, long arg2) { 13 | return arg1 | arg2; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/exception/NBTTagNotFound.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.exception; 2 | 3 | /** 4 | * Created with IntelliJ IDEA. 5 | * User: DPOH-VAR 6 | * Date: 14.09.13 7 | * Time: 14:16 8 | */ 9 | public class NBTTagNotFound extends NBTQueryException{ 10 | private final Object tag; 11 | public NBTTagNotFound(Object tag,Object tagName){ 12 | super("tag "+tagName+" not found"); 13 | this.tag = tag; 14 | } 15 | public Object getTag(){ 16 | return tag; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/utils/query/FreeIndexSelector.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.utils.query; 2 | 3 | public record FreeIndexSelector() implements IntegerSelector { 4 | 5 | public int indexToGet(int size){ 6 | return size - 1; 7 | } 8 | 9 | public int indexToDelete(int size){ 10 | return size - 1; 11 | } 12 | 13 | public int indexToSet(int size){ 14 | return size; 15 | } 16 | 17 | @Override 18 | public String toString() { 19 | return "[]"; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/exception/NBTReadException.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.exception; 2 | 3 | /** 4 | * Created by DPOH-VAR on 23.01.14 5 | */ 6 | public class NBTReadException extends RuntimeException { 7 | 8 | private final Object convert; 9 | 10 | public NBTReadException(Object convert){ 11 | super( (convert==null) ? "null" : convert.getClass().getSimpleName() + " is not valid NBT tag"); 12 | this.convert = convert; 13 | } 14 | 15 | public Object getConvertedObject(){ 16 | return convert; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/command/action/ActionCancel.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.command.action; 2 | 3 | import me.dpohvar.powernbt.utils.Caller; 4 | 5 | import static me.dpohvar.powernbt.PowerNBT.plugin; 6 | 7 | public class ActionCancel extends Action { 8 | 9 | private final Caller caller; 10 | 11 | public ActionCancel(Caller caller) { 12 | this.caller = caller; 13 | } 14 | 15 | @Override 16 | public void execute() { 17 | caller.hold(null,null); 18 | caller.send(plugin.translate("selection_cancel")); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/exception/NBTTagUnexpectedType.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.exception; 2 | 3 | /** 4 | * Created with IntelliJ IDEA. 5 | * User: DPOH-VAR 6 | * Date: 14.09.13 7 | * Time: 14:16 8 | */ 9 | public class NBTTagUnexpectedType extends NBTQueryException{ 10 | private final Object tag; 11 | public NBTTagUnexpectedType(Object tag, Class expected){ 12 | super("tag has wrong type "+tag.getClass().getSimpleName()+" but expected "+expected.getSimpleName()); 13 | this.tag = tag; 14 | } 15 | public Object getTag(){ 16 | return tag; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/utils/query/IndexSelector.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.utils.query; 2 | 3 | public record IndexSelector(int index) implements IntegerSelector { 4 | 5 | public int indexToGet(int size){ 6 | return index < 0 ? size + index : index; 7 | } 8 | 9 | public int indexToDelete(int size){ 10 | return index < 0 ? size + index : index; 11 | } 12 | 13 | public int indexToSet(int size){ 14 | return index < 0 ? size + index : index; 15 | } 16 | 17 | @Override 18 | public String toString() { 19 | return "["+index+"]"; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/utils/SimpleListener.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.utils; 2 | 3 | import me.dpohvar.powernbt.PowerNBT; 4 | import org.bukkit.Bukkit; 5 | import org.bukkit.event.HandlerList; 6 | import org.bukkit.event.Listener; 7 | 8 | public abstract class SimpleListener implements Listener { 9 | 10 | public final SimpleListener register() { 11 | Bukkit.getPluginManager().registerEvents(this, PowerNBT.plugin); 12 | return this; 13 | } 14 | 15 | public final SimpleListener unregister() { 16 | HandlerList.unregisterAll(this); 17 | return this; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/exception/NBTQueryException.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.exception; 2 | 3 | /** 4 | * Created with IntelliJ IDEA. 5 | * User: DPOH-VAR 6 | * Date: 14.09.13 7 | * Time: 14:13 8 | */ 9 | public class NBTQueryException extends Exception { 10 | 11 | public NBTQueryException(){ 12 | super(); 13 | } 14 | 15 | public NBTQueryException(String message){ 16 | super(message); 17 | } 18 | 19 | public NBTQueryException(Throwable cause){ 20 | super(cause); 21 | } 22 | 23 | public NBTQueryException(String message,Throwable cause){ 24 | super(message,cause); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/api/NBTBox.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.api; 2 | 3 | public interface NBTBox extends Cloneable { 4 | 5 | /** 6 | * Get original NBT tag. 7 | * @return NBTBase 8 | */ 9 | public Object getHandle(); 10 | 11 | /** 12 | * Get copy of original nbt box. 13 | * @return NBTTagCompound 14 | */ 15 | public Object getHandleCopy(); 16 | 17 | /** 18 | * Create clone of this NBT tag 19 | * @return cloned {@link NBTBox} 20 | */ 21 | public NBTBox clone(); 22 | 23 | public int size(); 24 | 25 | public boolean isEmpty(); 26 | 27 | } 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /src/main/resources/plugin.yml: -------------------------------------------------------------------------------- 1 | name: PowerNBT 2 | description: ${plugin-description} 3 | author: ${plugin-author} 4 | main: me.dpohvar.powernbt.PowerNBT 5 | api-version: ${api-version} 6 | website: ${plugin-website} 7 | version: ${plugin-version} 8 | softdepend: 9 | - VarScript 10 | commands: 11 | powernbt: 12 | description: use nbt commands 13 | usage: /nbt ... use [Tab] key for help 14 | permission: powernbt.use 15 | aliases: 16 | - pnbt 17 | - nbt 18 | powernbt.: 19 | description: use nbt commands (silent mode) 20 | usage: /nbt. ... use [Tab] key for help 21 | permission: powernbt.use 22 | aliases: 23 | - pnbt. 24 | - nbt. 25 | 26 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/utils/query/QSelector.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.utils.query; 2 | 3 | import me.dpohvar.powernbt.exception.NBTTagNotFound; 4 | 5 | public interface QSelector { 6 | 7 | /** 8 | * select next element by key 9 | * @return next element 10 | */ 11 | public Object get(Object current, boolean useDefault) throws NBTTagNotFound; 12 | 13 | /** 14 | * delete next element by key 15 | * @return current element 16 | */ 17 | public Object delete(Object current) throws NBTTagNotFound; 18 | 19 | /** 20 | * delete next element by key 21 | * @return current element 22 | */ 23 | public Object set(Object current, Object value, boolean createDir) throws NBTTagNotFound; 24 | 25 | public default String getSeparator(QSelector prevSelector){ 26 | return null; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /.github/workflows/maven-publish.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a package using Maven and then publish it to GitHub packages when a release is created 2 | # For more information see: https://github.com/actions/setup-java/blob/main/docs/advanced-usage.md#apache-maven-with-a-settings-path 3 | 4 | name: Maven Package 5 | 6 | on: 7 | release: 8 | types: [created] 9 | workflow_dispatch: 10 | 11 | jobs: 12 | build: 13 | runs-on: ubuntu-latest 14 | permissions: 15 | contents: read 16 | packages: write 17 | 18 | steps: 19 | - uses: actions/checkout@v2 20 | - name: Set up JDK 21 | uses: actions/setup-java@v2 22 | with: 23 | java-version: '17' 24 | distribution: 'adopt' 25 | 26 | - name: Publish package 27 | run: mvn --batch-mode -e deploy 28 | env: 29 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 30 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/extension/nbt/NBTCompoundProperties.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.extension.nbt; 2 | 3 | import groovy.lang.GroovyObjectSupport; 4 | import groovy.lang.MissingPropertyException; 5 | import me.dpohvar.powernbt.api.NBTCompound; 6 | 7 | public class NBTCompoundProperties extends GroovyObjectSupport{ 8 | 9 | private final NBTCompound handle; 10 | 11 | public NBTCompoundProperties(NBTCompound handle){ 12 | this.handle = handle; 13 | } 14 | 15 | @Override 16 | public Object getProperty(String property) { 17 | Object result = handle.get(property); 18 | if (result != null) return result; 19 | throw new MissingPropertyException(property, NBTCompound.class); 20 | } 21 | 22 | @Override 23 | public void setProperty(String property, Object newValue) { 24 | handle.put(property, newValue); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/exception/NBTConvertException.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.exception; 2 | 3 | /** 4 | * Created by DPOH-VAR on 23.01.14 5 | */ 6 | public class NBTConvertException extends RuntimeException { 7 | 8 | private final Object convert; 9 | 10 | private byte type = -1; 11 | 12 | public NBTConvertException(Object convert){ 13 | super("can't convert "+convert.getClass().getSimpleName()+" to NBTBase tag"); 14 | this.convert = convert; 15 | } 16 | 17 | public NBTConvertException(Object convert, byte type){ 18 | super("can't convert "+convert.getClass().getSimpleName()+" to NBT type "+type); 19 | this.convert = convert; 20 | this.type = type; 21 | } 22 | 23 | public Object getConvertedObject(){ 24 | return convert; 25 | } 26 | 27 | public byte getType() { 28 | return type; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/exception/ParseException.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.exception; 2 | 3 | /** 4 | * Created with IntelliJ IDEA. 5 | * User: DPOH-VAR 6 | * Date: 25.06.13 7 | * Time: 2:12 8 | */ 9 | public class ParseException extends SourceException { 10 | 11 | public ParseException(String string, int row, int col, String reason) { 12 | super(string, row, col, reason); 13 | } 14 | 15 | @Override 16 | public String getMessage() { 17 | String msg, reason; 18 | if (getCause() == null) { 19 | msg = super.getMessage(); 20 | reason = ""; 21 | } else { 22 | msg = getCause().getMessage(); 23 | reason = getCause().getClass().getSimpleName(); 24 | 25 | } 26 | return reason + " at [" + (row + 1) + ':' + (col + 1) + "]\n" + getErrorString() + (msg == null ? "" : '\n' + msg); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/utils/viewer/components/InteractiveElement.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.utils.viewer.components; 2 | 3 | import net.md_5.bungee.api.ChatColor; 4 | import net.md_5.bungee.api.chat.BaseComponent; 5 | import net.md_5.bungee.api.chat.ClickEvent; 6 | import net.md_5.bungee.api.chat.HoverEvent; 7 | import net.md_5.bungee.api.chat.TextComponent; 8 | 9 | public class InteractiveElement implements Element { 10 | 11 | private final TextComponent component; 12 | 13 | public InteractiveElement(ChatColor color, String buttonText, ClickEvent clickEvent, HoverEvent hoverEvent, String insertion){ 14 | component = new TextComponent(buttonText); 15 | if (color != null) component.setColor(color); 16 | if (clickEvent != null) component.setClickEvent(clickEvent); 17 | if (hoverEvent != null) component.setHoverEvent(hoverEvent); 18 | if (insertion != null) component.setInsertion(insertion); 19 | } 20 | 21 | @Override 22 | public BaseComponent getComponent() { 23 | return component; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/command/action/ActionCopy.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.command.action; 2 | 3 | import me.dpohvar.powernbt.PowerNBT; 4 | import me.dpohvar.powernbt.nbt.NBTContainer; 5 | import me.dpohvar.powernbt.utils.Caller; 6 | import me.dpohvar.powernbt.utils.query.NBTQuery; 7 | 8 | public class ActionCopy extends Action { 9 | 10 | private final Caller caller; 11 | private final Argument arg; 12 | 13 | public ActionCopy(Caller caller, String object, String query) { 14 | this.caller = caller; 15 | this.arg = new Argument(caller, object, query); 16 | } 17 | 18 | @Override 19 | public void execute() throws Exception { 20 | if (arg.needPrepare()) { 21 | arg.prepare(this, null, null); 22 | return; 23 | } 24 | NBTContainer container = arg.getContainer(); 25 | NBTQuery query = arg.getQuery(); 26 | Object base = container.getCustomTag(query); 27 | caller.setCustomTag(container.getCustomTag(query)); 28 | caller.sendValue(PowerNBT.plugin.translate("success_copied"), base,false, false); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Andrey Vakhterov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/command/action/ActionCut.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.command.action; 2 | 3 | import me.dpohvar.powernbt.PowerNBT; 4 | import me.dpohvar.powernbt.nbt.NBTContainer; 5 | import me.dpohvar.powernbt.utils.Caller; 6 | import me.dpohvar.powernbt.utils.query.NBTQuery; 7 | 8 | public class ActionCut extends Action { 9 | 10 | private final Caller caller; 11 | private final Argument arg; 12 | 13 | public ActionCut(Caller caller, String o1, String q1) { 14 | this.caller = caller; 15 | this.arg = new Argument(caller, o1, q1); 16 | } 17 | 18 | @Override 19 | public void execute() throws Exception { 20 | if (arg.needPrepare()) { 21 | arg.prepare(this, null, null); 22 | return; 23 | } 24 | NBTContainer container = arg.getContainer(); 25 | NBTQuery query = arg.getQuery(); 26 | Object base = container.getCustomTag(query); 27 | if (base == null) throw new RuntimeException(PowerNBT.plugin.translate("error_null")); 28 | caller.setCustomTag(base); 29 | caller.sendValue(PowerNBT.plugin.translate("success_cut"), base, false, false); 30 | arg.getContainer().removeTag(arg.getQuery()); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/utils/viewer/EventBuilder.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.utils.viewer; 2 | 3 | import net.md_5.bungee.api.chat.ClickEvent; 4 | import net.md_5.bungee.api.chat.HoverEvent; 5 | import net.md_5.bungee.api.chat.hover.content.Text; 6 | 7 | public class EventBuilder { 8 | 9 | public static ClickEvent runNbt(String powerNBTCommand, boolean silent){ 10 | String command = "/powernbt:nbt" + (silent ? ". " : " ") + powerNBTCommand; 11 | return new ClickEvent(ClickEvent.Action.RUN_COMMAND, command); 12 | } 13 | 14 | public static ClickEvent suggestNbt(String powerNBTCommand, boolean silent){ 15 | String command = "/powernbt:nbt" + (silent ? ". " : " ") + powerNBTCommand; 16 | return new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, command); 17 | } 18 | 19 | public static ClickEvent copy(String value){ 20 | return new ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, value); 21 | } 22 | 23 | public static ClickEvent url(String value){ 24 | return new ClickEvent(ClickEvent.Action.OPEN_URL, value); 25 | } 26 | 27 | public static HoverEvent popup(String value){ 28 | return new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text(value)); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/command/action/ActionDebug.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.command.action; 2 | 3 | import me.dpohvar.powernbt.PowerNBT; 4 | import me.dpohvar.powernbt.utils.Caller; 5 | 6 | import static me.dpohvar.powernbt.PowerNBT.plugin; 7 | 8 | public class ActionDebug extends Action { 9 | 10 | private final Caller caller; 11 | private final String value; 12 | 13 | public ActionDebug(Caller caller, String value) { 14 | this.caller = caller; 15 | this.value = value; 16 | } 17 | 18 | @Override 19 | public void execute() { 20 | boolean debug; 21 | if (value == null || value.equals("toggle")) { 22 | debug = !PowerNBT.plugin.isDebug(); 23 | } else { 24 | if (value.equals("on") || value.equals("enable") || value.equals("true")) { 25 | debug = true; 26 | } else if (value.equals("off") || value.equals("disable") || value.equals("false")) { 27 | debug = false; 28 | } else { 29 | throw new RuntimeException(plugin.translate("error_parsevalue", value)); 30 | } 31 | } 32 | plugin.setDebug(debug); 33 | if (debug) caller.send(plugin.translate("success_debug_on")); 34 | else caller.send(plugin.translate("success_debug_off")); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/utils/query/StringAsJsonSelector.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.utils.query; 2 | 3 | import me.dpohvar.powernbt.exception.NBTTagNotFound; 4 | import me.dpohvar.powernbt.utils.PowerJSONParser; 5 | 6 | public record StringAsJsonSelector() implements QSelector { 7 | 8 | @Override 9 | public Object get(Object current, boolean useDefault) throws NBTTagNotFound { 10 | if (useDefault && current == null) return null; 11 | if (current instanceof String string) { 12 | if (string.isEmpty()) return null; 13 | try { 14 | return PowerJSONParser.parse(string); 15 | } catch (Throwable t) { 16 | if (useDefault) return null; 17 | } 18 | } 19 | throw new NBTTagNotFound(current, this.toString()); 20 | } 21 | 22 | @Override 23 | public Object delete(Object current) throws NBTTagNotFound { 24 | if (current instanceof String) return ""; 25 | throw new NBTTagNotFound(current, this.toString()); 26 | } 27 | 28 | @Override 29 | public Object set(Object current, Object value, boolean createDir) throws NBTTagNotFound { 30 | return PowerJSONParser.stringify(value); 31 | } 32 | @Override 33 | public String toString() { 34 | return "#"; 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/utils/viewer/components/ButtonEdit.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.utils.viewer.components; 2 | 3 | import me.dpohvar.powernbt.utils.viewer.ContainerControl; 4 | import me.dpohvar.powernbt.utils.viewer.EventBuilder; 5 | import me.dpohvar.powernbt.utils.viewer.ViewerStyle; 6 | import net.md_5.bungee.api.chat.ClickEvent; 7 | import net.md_5.bungee.api.chat.HoverEvent; 8 | 9 | public class ButtonEdit extends InteractiveElement { 10 | 11 | static ButtonEdit create(ViewerStyle style, ContainerControl control){ 12 | ClickEvent click = getClickEvent(control); 13 | if (click == null) return null; 14 | return new ButtonEdit(style, click, getHoverEvent(control)); 15 | } 16 | 17 | private ButtonEdit(ViewerStyle style, ClickEvent click, HoverEvent hover){ 18 | super(style.getColor("buttons.control.edit"), style.getIcon("buttons.control.edit"), click, hover, null); 19 | } 20 | 21 | private static ClickEvent getClickEvent(ContainerControl control){ 22 | if (control.isReadonly()) return null; 23 | return EventBuilder.suggestNbt(control.getSelectorWithQuery()+" = ", false); 24 | } 25 | 26 | private static HoverEvent getHoverEvent(ContainerControl control){ 27 | if (control.isReadonly()) return null; 28 | return EventBuilder.popup("edit value"); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/utils/viewer/components/ButtonSelectJson.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.utils.viewer.components; 2 | 3 | import me.dpohvar.powernbt.utils.viewer.ContainerControl; 4 | import me.dpohvar.powernbt.utils.viewer.EventBuilder; 5 | import me.dpohvar.powernbt.utils.viewer.ViewerStyle; 6 | import net.md_5.bungee.api.chat.ClickEvent; 7 | import net.md_5.bungee.api.chat.HoverEvent; 8 | 9 | public class ButtonSelectJson extends InteractiveElement { 10 | 11 | static ButtonSelectJson create(ViewerStyle style, ContainerControl control){ 12 | ClickEvent click = getClickEvent(control); 13 | if (click == null) return null; 14 | return new ButtonSelectJson(style, click, getHoverEvent(control)); 15 | } 16 | 17 | private ButtonSelectJson(ViewerStyle style, ClickEvent click, HoverEvent hover){ 18 | super(style.getColor("buttons.control.selectJson"), style.getIcon("buttons.control.selectJson"), click, hover, null); 19 | } 20 | 21 | private static ClickEvent getClickEvent(ContainerControl control){ 22 | if (control.isReadonly()) return null; 23 | return EventBuilder.runNbt(control.getSelectorWithQuery()+"#", false); 24 | } 25 | 26 | private static HoverEvent getHoverEvent(ContainerControl control){ 27 | if (control.isReadonly()) return null; 28 | return EventBuilder.popup("select as json"); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/utils/viewer/components/ButtonCopyToBuffer.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.utils.viewer.components; 2 | 3 | import me.dpohvar.powernbt.utils.viewer.ContainerControl; 4 | import me.dpohvar.powernbt.utils.viewer.EventBuilder; 5 | import me.dpohvar.powernbt.utils.viewer.ViewerStyle; 6 | import net.md_5.bungee.api.chat.ClickEvent; 7 | import net.md_5.bungee.api.chat.HoverEvent; 8 | 9 | public class ButtonCopyToBuffer extends InteractiveElement { 10 | 11 | static ButtonCopyToBuffer create(ViewerStyle style, ContainerControl control){ 12 | ClickEvent click = getClickEvent(control); 13 | if (click == null) return null; 14 | return new ButtonCopyToBuffer(style, click, getHoverEvent(control)); 15 | } 16 | 17 | private ButtonCopyToBuffer(ViewerStyle style, ClickEvent click, HoverEvent hover){ 18 | super(style.getColor("buttons.control.copyToBuffer"), style.getIcon("buttons.control.copyToBuffer"), click, hover, null); 19 | } 20 | 21 | private static ClickEvent getClickEvent(ContainerControl control){ 22 | if (control.isReadonly()) return null; 23 | return EventBuilder.runNbt(control.getSelectorWithQuery()+" copy", true); 24 | } 25 | 26 | private static HoverEvent getHoverEvent(ContainerControl control){ 27 | if (control.isReadonly()) return null; 28 | return EventBuilder.popup("copy to buffer"); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/command/action/ActionRemove.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.command.action; 2 | 3 | import me.dpohvar.powernbt.PowerNBT; 4 | import me.dpohvar.powernbt.nbt.NBTContainer; 5 | import me.dpohvar.powernbt.utils.Caller; 6 | import me.dpohvar.powernbt.utils.query.NBTQuery; 7 | 8 | public class ActionRemove extends Action { 9 | 10 | private final Caller caller; 11 | private final Argument arg; 12 | private final String param; 13 | 14 | public ActionRemove(Caller caller, String object, String query, String param) { 15 | this.caller = caller; 16 | this.arg = new Argument(caller, object, query); 17 | this.param = param; 18 | } 19 | 20 | @Override 21 | public void execute() throws Exception { 22 | if (arg.needPrepare()) { 23 | arg.prepare(this, null, null); 24 | return; 25 | } 26 | NBTContainer container = arg.getContainer(); 27 | NBTQuery query = arg.getQuery(); 28 | Object base = null; 29 | try { 30 | base = container.getCustomTag(query); 31 | } catch (Exception ignored){} 32 | container.removeCustomTag(query); 33 | if (param != null) { 34 | new ActionView(caller, arg, param).execute(); 35 | } else { 36 | caller.sendValue(PowerNBT.plugin.translate("success_removed"), base, false, false); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/utils/viewer/components/ButtonPasteFromBuffer.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.utils.viewer.components; 2 | 3 | import me.dpohvar.powernbt.utils.viewer.ContainerControl; 4 | import me.dpohvar.powernbt.utils.viewer.EventBuilder; 5 | import me.dpohvar.powernbt.utils.viewer.ViewerStyle; 6 | import net.md_5.bungee.api.chat.ClickEvent; 7 | import net.md_5.bungee.api.chat.HoverEvent; 8 | 9 | public class ButtonPasteFromBuffer extends InteractiveElement { 10 | 11 | static ButtonPasteFromBuffer create(ViewerStyle style, ContainerControl control){ 12 | ClickEvent click = getClickEvent(control); 13 | if (click == null) return null; 14 | return new ButtonPasteFromBuffer(style, click, getHoverEvent(control)); 15 | } 16 | 17 | private ButtonPasteFromBuffer(ViewerStyle style, ClickEvent click, HoverEvent hover){ 18 | super(style.getColor("buttons.control.pasteFromBuffer"), style.getIcon("buttons.control.pasteFromBuffer"), click, hover, null); 19 | } 20 | 21 | private static ClickEvent getClickEvent(ContainerControl control){ 22 | if (control.isReadonly()) return null; 23 | return EventBuilder.runNbt(control.getSelectorWithQuery()+" paste", false); 24 | } 25 | 26 | private static HoverEvent getHoverEvent(ContainerControl control){ 27 | if (control.isReadonly()) return null; 28 | return EventBuilder.popup("paste from buffer"); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/nbt/NBTContainerFileGZipCustom.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.nbt; 2 | 3 | import me.dpohvar.powernbt.api.NBTCompound; 4 | import me.dpohvar.powernbt.utils.StringParser; 5 | 6 | import java.io.File; 7 | 8 | import static me.dpohvar.powernbt.PowerNBT.plugin; 9 | 10 | public class NBTContainerFileGZipCustom extends NBTContainerFileGZip { 11 | 12 | String name; 13 | 14 | public NBTContainerFileGZipCustom(String name) { 15 | super(getFileByName(name), "$$" + StringParser.wrapToQuotesIfNeeded(name)); 16 | this.name = name; 17 | } 18 | 19 | private static File getFileByName(String name){ 20 | if (name.contains(".") || name.contains(File.separator)) { 21 | throw new RuntimeException(plugin.translate("error_customfile", name)); 22 | } 23 | return new File(plugin.getNBTFilesFolder(), name + ".nbt.gz"); 24 | } 25 | 26 | @Override 27 | public Object readTag() { 28 | Object value = super.readTag(); 29 | if (value instanceof NBTCompound compound) { 30 | return compound.get("Data"); 31 | } 32 | return value; 33 | } 34 | 35 | @Override 36 | public void writeTag(Object base) { 37 | if (isNBT(base)) { 38 | NBTCompound compound = new NBTCompound(); 39 | compound.put("Data", base); 40 | super.writeTag(compound); 41 | } else { // json 42 | super.writeTag(base); 43 | } 44 | 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/command/Command.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.command; 2 | 3 | import me.dpohvar.powernbt.utils.Caller; 4 | import org.apache.commons.lang.StringUtils; 5 | import org.bukkit.command.CommandExecutor; 6 | import org.bukkit.command.CommandSender; 7 | 8 | import java.util.LinkedList; 9 | import java.util.logging.Level; 10 | 11 | import static me.dpohvar.powernbt.PowerNBT.plugin; 12 | 13 | public abstract class Command implements CommandExecutor { 14 | 15 | private final boolean silent; 16 | 17 | public Command(boolean silent){ 18 | this.silent = silent; 19 | } 20 | 21 | @Override 22 | public boolean onCommand(CommandSender sender, org.bukkit.command.Command command, String label, String[] args) { 23 | Caller caller = plugin.getCaller(sender); 24 | caller.setSilent(silent); 25 | try { 26 | LinkedList words = new LinkedList<>(); 27 | for (String s : plugin.getTokenizer().tokenize(StringUtils.join(args, ' ')).values()) { 28 | words.add(s); 29 | } 30 | return command(caller, words); 31 | } catch (Throwable t) { 32 | caller.handleException(t); 33 | if (plugin.isDebug()) { 34 | plugin.getLogger().log(Level.WARNING, "Exception on command: "+label, t); 35 | } 36 | return true; 37 | } 38 | } 39 | 40 | abstract protected boolean command(Caller caller, LinkedList words) throws Throwable; 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/command/action/ActionEdit.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.command.action; 2 | 3 | import me.dpohvar.powernbt.PowerNBT; 4 | import me.dpohvar.powernbt.nbt.NBTContainer; 5 | import me.dpohvar.powernbt.utils.Caller; 6 | import me.dpohvar.powernbt.utils.query.NBTQuery; 7 | 8 | public class ActionEdit extends Action { 9 | 10 | private final Caller caller; 11 | private final Argument arg1; 12 | private final Argument arg2; 13 | 14 | public ActionEdit(Caller caller, String o1, String q1, String o2, String q2) { 15 | this.caller = caller; 16 | this.arg1 = new Argument(caller, o1, q1); 17 | this.arg2 = new Argument(caller, o2, q2); 18 | } 19 | 20 | @Override 21 | public void execute() throws Exception { 22 | if (arg1.needPrepare()) { 23 | arg1.prepare(this, null, null); 24 | return; 25 | } 26 | NBTContainer container = arg1.getContainer(); 27 | NBTQuery query = arg1.getQuery(); 28 | if (arg2.needPrepare()) { 29 | arg2.prepare(this, container, query); 30 | return; 31 | } 32 | Object base = arg2.getContainer().getCustomTag(arg2.getQuery()); 33 | try{ 34 | container.setCustomTag(query, base); 35 | caller.sendValue(PowerNBT.plugin.translate("success_edit"), base, false, false); 36 | } catch (Exception e){ 37 | throw new RuntimeException( PowerNBT.plugin.translate("fail_edit", query.toString()) , e); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/utils/viewer/components/ButtonCopyToClipboard.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.utils.viewer.components; 2 | 3 | import me.dpohvar.powernbt.nbt.NBTContainer; 4 | import me.dpohvar.powernbt.utils.viewer.ContainerControl; 5 | import me.dpohvar.powernbt.utils.viewer.EventBuilder; 6 | import me.dpohvar.powernbt.utils.viewer.ViewerStyle; 7 | import net.md_5.bungee.api.chat.ClickEvent; 8 | import net.md_5.bungee.api.chat.HoverEvent; 9 | 10 | public class ButtonCopyToClipboard extends InteractiveElement { 11 | 12 | static ButtonCopyToClipboard create(ViewerStyle style, ContainerControl control){ 13 | ClickEvent click = getClickEvent(control); 14 | if (click == null) return null; 15 | return new ButtonCopyToClipboard(style, click, getHoverEvent(control)); 16 | } 17 | 18 | private ButtonCopyToClipboard(ViewerStyle style, ClickEvent click, HoverEvent hover){ 19 | super(style.getColor("buttons.control.copyToClipboard"), style.getIcon("buttons.control.copyToClipboard"), click, hover, null); 20 | } 21 | 22 | private static ClickEvent getClickEvent(ContainerControl control){ 23 | if (control.hasValue()) return null; 24 | String clipboardValue = NBTContainer.parseValueToSelector(control.getValue(), 255); 25 | if (clipboardValue == null) return null; 26 | return EventBuilder.copy(clipboardValue); 27 | } 28 | 29 | private static HoverEvent getHoverEvent(ContainerControl control){ 30 | if (control.hasValue()) return null; 31 | return EventBuilder.popup("copy value to clipboard"); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/command/action/ActionBitInverse.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.command.action; 2 | 3 | import me.dpohvar.powernbt.api.NBTManagerUtils; 4 | import me.dpohvar.powernbt.nbt.NBTContainer; 5 | import me.dpohvar.powernbt.nbt.NBTType; 6 | import me.dpohvar.powernbt.utils.Caller; 7 | import me.dpohvar.powernbt.utils.query.NBTQuery; 8 | 9 | import static me.dpohvar.powernbt.PowerNBT.plugin; 10 | 11 | public class ActionBitInverse extends Action { 12 | 13 | private final Caller caller; 14 | private final Argument arg1; 15 | 16 | public ActionBitInverse(Caller caller, String o1, String q1) { 17 | this.caller = caller; 18 | this.arg1 = new Argument(caller, o1, q1); 19 | } 20 | 21 | @Override 22 | public void execute() throws Exception { 23 | if (arg1.needPrepare()) { 24 | arg1.prepare(this, null, null); 25 | return; 26 | } 27 | NBTContainer container1 = arg1.getContainer(); 28 | NBTQuery query1 = arg1.getQuery(); 29 | Object base1 = container1.getCustomTag(query1); 30 | Object result; 31 | if (base1 instanceof Number num) { 32 | result = NBTManagerUtils.convertValue(~(num.longValue()), NBTType.fromValue(base1).type); 33 | } else if (base1 instanceof Boolean bool) { 34 | result = !bool; 35 | } else { 36 | throw new RuntimeException(plugin.translate("error_null")); 37 | } 38 | container1.setCustomTag(query1, result); 39 | caller.sendValue(plugin.translate("success_edit"), result, false, false); 40 | 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/utils/viewer/components/ButtonUpdate.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.utils.viewer.components; 2 | 3 | import me.dpohvar.powernbt.utils.viewer.ContainerControl; 4 | import me.dpohvar.powernbt.utils.viewer.EventBuilder; 5 | import me.dpohvar.powernbt.utils.viewer.ViewerStyle; 6 | import net.md_5.bungee.api.chat.ClickEvent; 7 | import net.md_5.bungee.api.chat.HoverEvent; 8 | 9 | public class ButtonUpdate extends InteractiveElement { 10 | 11 | static ButtonUpdate create(ViewerStyle style, ContainerControl control, String parentAccess){ 12 | ClickEvent click = getClickEvent(control, parentAccess); 13 | if (click == null) return null; 14 | return new ButtonUpdate(style, click, getHoverEvent(control)); 15 | } 16 | 17 | private ButtonUpdate(ViewerStyle style, ClickEvent click, HoverEvent hover){ 18 | super(style.getColor("buttons.control.update"), style.getIcon("buttons.control.update"), click, hover, null); 19 | } 20 | 21 | private static ClickEvent getClickEvent(ContainerControl control, String parentAccess){ 22 | if (control.isReadonly()) return null; 23 | String parentPart; 24 | if (parentAccess == null) parentPart = ""; 25 | else if (parentAccess.isEmpty()) parentPart = " ,"; 26 | else parentPart = " " + parentAccess; 27 | return EventBuilder.runNbt(control.getSelectorWithQuery() + parentPart, false); 28 | } 29 | 30 | private static HoverEvent getHoverEvent(ContainerControl control){ 31 | if (control.isReadonly()) return null; 32 | return EventBuilder.popup("update value"); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/utils/viewer/components/ButtonRemove.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.utils.viewer.components; 2 | 3 | import me.dpohvar.powernbt.utils.viewer.ContainerControl; 4 | import me.dpohvar.powernbt.utils.viewer.EventBuilder; 5 | import me.dpohvar.powernbt.utils.viewer.ViewerStyle; 6 | import net.md_5.bungee.api.chat.ClickEvent; 7 | import net.md_5.bungee.api.chat.HoverEvent; 8 | 9 | public class ButtonRemove extends InteractiveElement { 10 | 11 | static ButtonRemove create(ViewerStyle style, ContainerControl control, String parentAccess){ 12 | ClickEvent click = getClickEvent(control, parentAccess); 13 | if (click == null) return null; 14 | return new ButtonRemove(style, click, getHoverEvent(control)); 15 | } 16 | 17 | private ButtonRemove(ViewerStyle style, ClickEvent click, HoverEvent hover){ 18 | super(style.getColor("buttons.control.remove"), style.getIcon("buttons.control.remove"), click, hover, null); 19 | } 20 | 21 | private static ClickEvent getClickEvent(ContainerControl control, String parentAccess){ 22 | if (control.isReadonly()) return null; 23 | String parentPart; 24 | if (parentAccess == null) parentPart = ""; 25 | else if (parentAccess.isEmpty()) parentPart = " ,"; 26 | else parentPart = " " + parentAccess; 27 | return EventBuilder.runNbt(control.getSelectorWithQuery() + " remove" + parentPart, false); 28 | } 29 | 30 | private static HoverEvent getHoverEvent(ContainerControl control){ 31 | if (control.isReadonly()) return null; 32 | return EventBuilder.popup("remove value"); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/nbt/NBTContainerChunk.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.nbt; 2 | 3 | import me.dpohvar.powernbt.api.NBTCompound; 4 | import me.dpohvar.powernbt.api.NBTManager; 5 | import me.dpohvar.powernbt.utils.StringParser; 6 | import org.bukkit.Chunk; 7 | 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | import java.util.Map; 11 | 12 | public class NBTContainerChunk extends NBTContainer { 13 | 14 | Chunk chunk; 15 | 16 | public NBTContainerChunk(Chunk chunk) { 17 | super("chunk:"+chunk.getX()+":"+chunk.getZ()+":"+ StringParser.wrapToQuotesIfNeeded(chunk.getWorld().getName())); 18 | this.chunk = chunk; 19 | } 20 | 21 | public Chunk getObject() { 22 | return chunk; 23 | } 24 | 25 | @Override 26 | public List getTypes() { 27 | List s = new ArrayList<>(); 28 | s.add("chunk"); 29 | return s; 30 | } 31 | 32 | @Override 33 | public NBTCompound readTag() { 34 | return NBTManager.getInstance().read(chunk); 35 | } 36 | 37 | @Override 38 | public void writeTag(Object value) { 39 | NBTCompound compound = null; 40 | if (value instanceof NBTCompound c) compound = c; 41 | else if (value instanceof Map map) compound = new NBTCompound(map); 42 | if (compound == null) return; 43 | NBTManager.getInstance().write(chunk, compound); 44 | } 45 | 46 | @Override 47 | protected Class getContainerClass() { 48 | return Chunk.class; 49 | } 50 | 51 | @Override 52 | public String toString(){ 53 | return chunk.toString(); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/nbt/NBTContainerValue.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.nbt; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | public class NBTContainerValue extends NBTContainer { 7 | 8 | private Object base; 9 | private final String selectorTag; 10 | 11 | public NBTContainerValue(Object base) { 12 | this(base, null); 13 | } 14 | 15 | public NBTContainerValue(Object base, String selectorTag) { 16 | super(null); 17 | this.base = base; 18 | this.selectorTag = selectorTag; 19 | } 20 | 21 | @Override 22 | public String getSelector() { 23 | if (selectorTag != null) return selectorTag; 24 | return NBTContainer.parseValueToSelector(base); 25 | } 26 | 27 | @Override 28 | public Object getObject() { 29 | return base; 30 | } 31 | 32 | @Override 33 | public List getTypes() { 34 | return new ArrayList<>(); 35 | } 36 | 37 | @Override 38 | public Object readTag() { 39 | return this.base; 40 | } 41 | 42 | @Override 43 | public void writeTag(Object base) { 44 | this.base = base; 45 | } 46 | 47 | @Override 48 | public void eraseTag() { 49 | this.base = null; 50 | } 51 | 52 | @Override 53 | protected Class getContainerClass() { 54 | return Object.class; 55 | } 56 | 57 | @Override 58 | public String toString(){ 59 | return base == null ? "null" : base.getClass().getSimpleName(); 60 | } 61 | 62 | @Override 63 | public boolean isObjectReadonly(){ 64 | return true; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/nbt/NBTContainerItem.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.nbt; 2 | 3 | import me.dpohvar.powernbt.api.NBTCompound; 4 | import me.dpohvar.powernbt.api.NBTManager; 5 | import org.bukkit.inventory.ItemStack; 6 | import org.bukkit.inventory.meta.ItemMeta; 7 | 8 | import java.util.Map; 9 | 10 | public class NBTContainerItem extends NBTContainer { 11 | 12 | private final ItemStack item; 13 | 14 | public NBTContainerItem(ItemStack item) { 15 | this(item, null); 16 | } 17 | 18 | public NBTContainerItem(ItemStack item, String selectorTag) { 19 | super(selectorTag); 20 | this.item = item; 21 | } 22 | 23 | public ItemStack getObject() { 24 | return item; 25 | } 26 | 27 | @Override 28 | public NBTCompound readTag() { 29 | return NBTManager.getInstance().read(item); 30 | } 31 | 32 | @Override 33 | public void writeTag(Object value) { 34 | NBTCompound compound = null; 35 | if (value instanceof NBTCompound c) compound = c; 36 | else if (value instanceof Map map) compound = new NBTCompound(map); 37 | if (compound == null) return; 38 | NBTManager.getInstance().write(item, compound.clone()); 39 | } 40 | 41 | @Override 42 | public void eraseTag() { 43 | writeTag(null); 44 | } 45 | 46 | @Override 47 | protected Class getContainerClass() { 48 | return ItemStack.class; 49 | } 50 | 51 | @Override 52 | public String toString(){ 53 | ItemMeta itemMeta = item.getItemMeta(); 54 | if (itemMeta != null) return itemMeta.getDisplayName(); 55 | return item.getType().name(); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/command/action/ActionMove.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.command.action; 2 | 3 | import me.dpohvar.powernbt.PowerNBT; 4 | import me.dpohvar.powernbt.nbt.NBTContainer; 5 | import me.dpohvar.powernbt.utils.Caller; 6 | import me.dpohvar.powernbt.utils.query.NBTQuery; 7 | 8 | public class ActionMove extends Action { 9 | 10 | private final Caller caller; 11 | private final Argument arg1; 12 | private final Argument arg2; 13 | 14 | public ActionMove(Caller caller, String o1, String q1, String o2, String q2) { 15 | this.caller = caller; 16 | this.arg1 = new Argument(caller, o1, q1); 17 | this.arg2 = new Argument(caller, o2, q2); 18 | } 19 | 20 | @Override 21 | public void execute() throws Exception { 22 | if (arg1.needPrepare()) { 23 | arg1.prepare(this, null, null); 24 | return; 25 | } 26 | NBTContainer container = arg1.getContainer(); 27 | NBTQuery query = arg1.getQuery(); 28 | if (arg2.needPrepare()) { 29 | arg2.prepare(this, container, query); 30 | return; 31 | } 32 | Object base = arg2.getContainer().getCustomTag(arg2.getQuery()); 33 | if (base == null) throw new RuntimeException(PowerNBT.plugin.translate("error_null")); 34 | 35 | try{ 36 | container.setCustomTag(query, base); 37 | arg2.getContainer().removeTag(arg2.getQuery()); 38 | caller.sendValue(PowerNBT.plugin.translate("success_move"), base, false, false); 39 | } catch (Exception e) { 40 | throw new RuntimeException(PowerNBT.plugin.translate("fail_move", query.toString()),e); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/command/action/ActionEditLast.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.command.action; 2 | 3 | import me.dpohvar.powernbt.PowerNBT; 4 | import me.dpohvar.powernbt.nbt.NBTContainer; 5 | import me.dpohvar.powernbt.utils.Caller; 6 | import me.dpohvar.powernbt.utils.query.NBTQuery; 7 | 8 | public class ActionEditLast extends Action { 9 | 10 | private final Caller caller; 11 | private final Argument arg1; 12 | private final Argument arg2; 13 | 14 | public ActionEditLast(Caller caller, String o1, String q1, String o2, String q2) { 15 | this.caller = caller; 16 | this.arg1 = new Argument(caller, o1, q1); 17 | this.arg2 = new Argument(caller, o2, q2); 18 | } 19 | 20 | @Override 21 | public void execute() throws Exception { 22 | if (arg1.needPrepare()) { 23 | arg1.prepare(this, null, null); 24 | return; 25 | } 26 | NBTContainer container1 = arg1.getContainer(); 27 | NBTQuery query1 = arg1.getQuery(); 28 | if (arg2.needPrepare()) { 29 | arg2.prepare(this, container1, query1); 30 | return; 31 | } 32 | NBTContainer container2 = arg2.getContainer(); 33 | NBTQuery query2 = arg2.getQuery(); 34 | Object base = arg1.getContainer().getCustomTag(arg1.getQuery()); 35 | if (base == null) throw new RuntimeException(PowerNBT.plugin.translate("error_null")); 36 | try{ 37 | container2.setCustomTag(query2, base); 38 | caller.sendValue(PowerNBT.plugin.translate("success_edit"), base, false, false); 39 | } catch (Exception e){ 40 | throw new RuntimeException( PowerNBT.plugin.translate("fail_edit", query2.toString()) , e); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /.github/workflows/create-gh-release.yml: -------------------------------------------------------------------------------- 1 | # This is a basic workflow to help you get started with Actions 2 | 3 | name: Create GH release 4 | 5 | # Controls when the workflow will run 6 | on: 7 | push: 8 | branches: 9 | - master 10 | tags: 11 | - v* 12 | create: 13 | tags: 14 | - v* 15 | 16 | jobs: 17 | build: 18 | if: github.event.ref_type == 'tag' && startsWith(github.event.ref, 'v') 19 | runs-on: ubuntu-latest 20 | 21 | steps: 22 | - uses: actions/checkout@v2 23 | - name: Set up JDK 24 | uses: actions/setup-java@v2 25 | with: 26 | java-version: '17' 27 | distribution: 'adopt' 28 | 29 | - name: Retrive version from tag 30 | id: version 31 | run: | 32 | echo "::set-output name=ver::$(echo ${{ github.event.ref }} | egrep -o '[[:digit:]]{1,4}(.[[:digit:]]{1,4}){1,3}')" 33 | 34 | - name: MVN build package 35 | run: mvn --batch-mode -Dplugin-version=${{steps.version.outputs.ver}} package 36 | 37 | - name: Create Release 38 | id: create_release 39 | uses: actions/create-release@v1 40 | env: 41 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 42 | with: 43 | tag_name: ${{ github.event.ref }} 44 | release_name: PowerNBT ${{ steps.version.outputs.ver }} 45 | draft: false 46 | prerelease: false 47 | 48 | - name: Upload Release Asset 49 | id: upload_release_asset 50 | uses: actions/upload-release-asset@v1 51 | env: 52 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 53 | with: 54 | upload_url: ${{ steps.create_release.outputs.upload_url }} 55 | asset_path: target/powernbt.jar 56 | asset_name: PowerNBT.jar 57 | asset_content_type: application/zip 58 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/command/action/ActionMoveLast.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.command.action; 2 | 3 | import me.dpohvar.powernbt.PowerNBT; 4 | import me.dpohvar.powernbt.nbt.NBTContainer; 5 | import me.dpohvar.powernbt.utils.Caller; 6 | import me.dpohvar.powernbt.utils.query.NBTQuery; 7 | 8 | public class ActionMoveLast extends Action { 9 | 10 | private final Caller caller; 11 | private final Argument arg1; 12 | private final Argument arg2; 13 | 14 | public ActionMoveLast(Caller caller, String o1, String q1, String o2, String q2) { 15 | this.caller = caller; 16 | this.arg1 = new Argument(caller, o1, q1); 17 | this.arg2 = new Argument(caller, o2, q2); 18 | } 19 | 20 | @Override 21 | public void execute() throws Exception { 22 | if (arg1.needPrepare()) { 23 | arg1.prepare(this, null, null); 24 | return; 25 | } 26 | NBTContainer container1 = arg1.getContainer(); 27 | NBTQuery query1 = arg1.getQuery(); 28 | if (arg2.needPrepare()) { 29 | arg2.prepare(this, container1, query1); 30 | return; 31 | } 32 | NBTQuery query2 = arg2.getQuery(); 33 | NBTContainer container2 = arg2.getContainer(); 34 | Object base = arg1.getContainer().getCustomTag(arg1.getQuery()); 35 | if (base == null) throw new RuntimeException(PowerNBT.plugin.translate("error_null")); 36 | 37 | try{ 38 | container2.setCustomTag(query2, base); 39 | arg1.getContainer().removeTag(arg1.getQuery()); 40 | caller.sendValue(PowerNBT.plugin.translate("success_move"), base, false, false); 41 | } catch (Exception e) { 42 | throw new RuntimeException(PowerNBT.plugin.translate("fail_move", query2.toString()),e); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/command/action/ActionSwap.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.command.action; 2 | 3 | import me.dpohvar.powernbt.PowerNBT; 4 | import me.dpohvar.powernbt.nbt.NBTContainer; 5 | import me.dpohvar.powernbt.utils.Caller; 6 | import me.dpohvar.powernbt.utils.query.NBTQuery; 7 | 8 | public class ActionSwap extends Action { 9 | 10 | private final Caller caller; 11 | private final Argument arg1; 12 | private final Argument arg2; 13 | 14 | public ActionSwap(Caller caller, String o1, String q1, String o2, String q2) { 15 | this.caller = caller; 16 | this.arg1 = new Argument(caller, o1, q1); 17 | this.arg2 = new Argument(caller, o2, q2); 18 | } 19 | 20 | @Override 21 | public void execute() throws Exception { 22 | if (arg1.needPrepare()) { 23 | arg1.prepare(this, null, null); 24 | return; 25 | } 26 | NBTContainer container1 = arg1.getContainer(); 27 | NBTQuery query1 = arg1.getQuery(); 28 | if (arg2.needPrepare()) { 29 | arg2.prepare(this, container1, query1); 30 | return; 31 | } 32 | NBTContainer container2 = arg2.getContainer(); 33 | NBTQuery query2 = arg2.getQuery(); 34 | Object base1 = container1.getCustomTag(query1); 35 | Object base2 = container2.getCustomTag(query2); 36 | if (base1 == null && base2 == null) { 37 | caller.send(PowerNBT.plugin.translate("success_swap_null")); 38 | return; 39 | } 40 | if (base2 == null) container1.removeTag(query1); 41 | else container1.setCustomTag(query1, base2); 42 | if (base1 == null) container2.removeTag(query2); 43 | else container2.setCustomTag(query2, base1); 44 | caller.send(PowerNBT.plugin.translate("success_swap")); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/command/action/ActionRename.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.command.action; 2 | 3 | import me.dpohvar.powernbt.PowerNBT; 4 | import me.dpohvar.powernbt.nbt.NBTContainer; 5 | import me.dpohvar.powernbt.utils.Caller; 6 | import me.dpohvar.powernbt.utils.query.NBTQuery; 7 | import me.dpohvar.powernbt.utils.query.QSelector; 8 | 9 | import java.util.List; 10 | 11 | public class ActionRename extends Action { 12 | 13 | private final Caller caller; 14 | private final Argument arg1; 15 | private final String name; 16 | private final NBTQuery query2; 17 | 18 | public ActionRename(Caller caller, String o1, String q1, String name) { 19 | this.caller = caller; 20 | this.arg1 = new Argument(caller, o1, q1); 21 | this.name = name; 22 | this.query2 = NBTQuery.fromString(name); 23 | } 24 | 25 | @Override 26 | public void execute() throws Exception { 27 | if (arg1.needPrepare()) { 28 | arg1.prepare(this, null, null); 29 | return; 30 | } 31 | NBTContainer container = arg1.getContainer(); 32 | NBTQuery query = arg1.getQuery(); 33 | List v = query.getParent().getSelectors(); 34 | v.addAll(query2.getSelectors()); 35 | NBTQuery newQuery = new NBTQuery(v); 36 | Object root = container.getTag(); 37 | Object base = query.get(root); 38 | if (base == null) { 39 | caller.send(PowerNBT.plugin.translate("fail_rename")); 40 | } else { 41 | root = query.remove(root); 42 | root = newQuery.set(root,base); 43 | container.setCustomTag(root); 44 | caller.sendValue(PowerNBT.plugin.translate("success_rename", name), base, false, false); 45 | } 46 | } 47 | } 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/exception/SourceException.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.exception; 2 | 3 | import org.bukkit.ChatColor; 4 | 5 | /** 6 | * Created with IntelliJ IDEA. 7 | * User: DPOH-VAR 8 | * Date: 30.06.13 9 | * Time: 11:20 10 | */ 11 | public abstract class SourceException extends RuntimeException { 12 | protected String source; 13 | protected int row, col; 14 | 15 | public SourceException(String source, int row, int col, Throwable reason) { 16 | super(reason); 17 | this.source = source; 18 | this.row = row; 19 | this.col = col; 20 | } 21 | 22 | public SourceException(String source, int row, int col, String reason) { 23 | super(reason); 24 | this.source = source; 25 | this.row = row; 26 | this.col = col; 27 | } 28 | 29 | public String getErrorString() { 30 | if (source == null) return ChatColor.translateAlternateColorCodes('&', "&c[no source]&r"); 31 | String[] lines = source.split("\n"); 32 | if (lines.length == row) return ChatColor.translateAlternateColorCodes('&', "&e[end of source]&r"); 33 | else if (lines.length < row) return ChatColor.translateAlternateColorCodes('&', "&c[unknown source]&r"); 34 | String line = lines[row]; 35 | if (col == line.length()) return ChatColor.translateAlternateColorCodes('&', "&e[end of line]&r ") + line; 36 | if (col > line.length()) return ChatColor.translateAlternateColorCodes('&', "&c[unknown position]&r ") + line; 37 | StringBuilder builder = new StringBuilder(); 38 | builder.append(line.substring(0, col)); 39 | builder.append(ChatColor.RED); 40 | builder.append(line.charAt(col)); 41 | builder.append(ChatColor.RESET); 42 | builder.append(line.substring(col + 1)); 43 | return builder.toString(); 44 | } 45 | 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/utils/PowerJSONParser.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.utils; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.GsonBuilder; 5 | 6 | import java.io.*; 7 | import java.util.zip.GZIPInputStream; 8 | import java.util.zip.GZIPOutputStream; 9 | 10 | public class PowerJSONParser { 11 | 12 | private static final Gson gson = new GsonBuilder().serializeNulls().disableHtmlEscaping().create(); 13 | 14 | public static Object parse(String value){ 15 | return gson.fromJson(value, Object.class); 16 | } 17 | 18 | public static String stringify(Object value){ 19 | return gson.toJson(value); 20 | } 21 | 22 | public static void write(Object value, Writer writer) throws IOException{ 23 | gson.toJson(value, writer); 24 | } 25 | 26 | public static Object read(Reader reader) throws IOException{ 27 | return gson.fromJson(reader, Object.class); 28 | } 29 | 30 | public static void write(Object value, File file) throws IOException { 31 | try (var writer = new FileWriter(file)) { 32 | write(value, writer); 33 | } 34 | } 35 | 36 | public static Object read(File file) throws IOException { 37 | try (var reader = new FileReader(file)) { 38 | return read(reader); 39 | } 40 | } 41 | public static void writeCompressed(Object value, File file) throws IOException { 42 | try (var writer = new OutputStreamWriter(new BufferedOutputStream(new GZIPOutputStream(new FileOutputStream(file))))) { 43 | write(value, writer); 44 | } 45 | } 46 | 47 | public static Object readCompressed(File file) throws IOException { 48 | try (var reader = new InputStreamReader(new BufferedInputStream(new GZIPInputStream(new FileInputStream(file))))) { 49 | return read(reader); 50 | } 51 | } 52 | 53 | 54 | } -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/command/action/ActionSet.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.command.action; 2 | 3 | import me.dpohvar.powernbt.PowerNBT; 4 | import me.dpohvar.powernbt.nbt.NBTContainer; 5 | import me.dpohvar.powernbt.nbt.NBTContainerComplex; 6 | import me.dpohvar.powernbt.nbt.NBTContainerVariable; 7 | import me.dpohvar.powernbt.utils.Caller; 8 | import me.dpohvar.powernbt.utils.query.NBTQuery; 9 | 10 | public class ActionSet extends Action { 11 | 12 | private final Caller caller; 13 | private final Argument arg1; 14 | private final Argument arg2; 15 | 16 | public ActionSet(Caller caller, String o1, String o2, String q2) { 17 | this.caller = caller; 18 | if (o2 == null && q2 == null) o2 = "*"; 19 | this.arg1 = new Argument(caller, o1, null); 20 | this.arg2 = new Argument(caller, o2, q2); 21 | } 22 | 23 | @Override 24 | public void execute() throws Exception { 25 | if (arg1.needPrepare()) { 26 | arg1.prepare(this, null, null); 27 | return; 28 | } 29 | NBTContainer containerVar = arg1.getContainer(); 30 | if (!(containerVar instanceof NBTContainerVariable)) { 31 | throw new RuntimeException(PowerNBT.plugin.translate("error_variablerequired")); 32 | } 33 | NBTContainerVariable variable = (NBTContainerVariable) containerVar; 34 | if (arg2.needPrepare()) { 35 | arg2.prepare(this, containerVar, null); 36 | return; 37 | } 38 | NBTContainer container = arg2.getContainer(); 39 | NBTQuery query = arg2.getQuery(); 40 | if (query != null && !query.isEmpty()) { 41 | container = new NBTContainerComplex(container, query); 42 | } 43 | variable.setContainer(container); 44 | caller.send(PowerNBT.plugin.translate("success_select", container.toString(), variable.getVariableName())); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/api/NBTBridge.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.api; 2 | 3 | import org.bukkit.World; 4 | import org.bukkit.block.BlockState; 5 | import org.bukkit.entity.Entity; 6 | import org.bukkit.inventory.ItemStack; 7 | 8 | import java.io.DataInput; 9 | import java.io.DataOutput; 10 | import java.io.IOException; 11 | import java.util.List; 12 | import java.util.Map; 13 | 14 | abstract class NBTBridge { 15 | 16 | private static NBTBridge instance; 17 | 18 | public static NBTBridge getInstance(){ 19 | if (instance == null) instance = new NBTBridgeSpigot(); 20 | return instance; 21 | } 22 | 23 | abstract Map getNbtInnerMap(Object nbtTagCompound); 24 | 25 | abstract List getNbtInnerList(Object nbtTagList); 26 | 27 | abstract Object getBlockNBTTag(BlockState state); 28 | 29 | abstract Object getEntityNBTTag(Entity entity); 30 | 31 | abstract Object getItemStackNBTTag(ItemStack itemStack); 32 | 33 | abstract void setBlockNBTTag(BlockState state, Object tag); 34 | 35 | abstract void setEntityNBTTag(Entity entity, Object tag); 36 | 37 | abstract void setItemStackNBTTag(ItemStack itemStack, Object tag); 38 | 39 | abstract ItemStack asCraftCopyItemStack(ItemStack itemStack); 40 | 41 | abstract Object readNBTData(DataInput dataInput, byte type) throws IOException; 42 | 43 | abstract void writeNBTData(DataOutput dataInput, Object tag) throws IOException; 44 | 45 | abstract Entity spawnEntity(Object tag, World world); 46 | 47 | abstract byte getTagType(Object tag); 48 | 49 | abstract Object getPrimitiveValue(Object tag); 50 | 51 | abstract Object getTagValueByPrimitive(Object javaPrimitive); 52 | 53 | abstract Object cloneTag(Object tag); 54 | 55 | abstract Object createNBTTagCompound(); 56 | 57 | abstract Object createNBTTagList(); 58 | 59 | abstract byte getNBTTagListType(Object tagList); 60 | 61 | abstract void setNBTTagListType(Object tagList, byte type); 62 | 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/nbt/NBTContainerFileGZip.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.nbt; 2 | 3 | import me.dpohvar.powernbt.api.NBTManager; 4 | import me.dpohvar.powernbt.utils.PowerJSONParser; 5 | import me.dpohvar.powernbt.utils.StringParser; 6 | 7 | import java.io.File; 8 | import java.io.FileNotFoundException; 9 | import java.io.IOException; 10 | import java.util.ArrayList; 11 | import java.util.List; 12 | 13 | public class NBTContainerFileGZip extends NBTContainerFile { 14 | 15 | 16 | public NBTContainerFileGZip(File file) { 17 | super(file, "gz:"+ StringParser.wrapToQuotesIfNeeded(file.toString())); 18 | } 19 | 20 | protected NBTContainerFileGZip(File file, String selector) { 21 | super(file, selector); 22 | } 23 | 24 | @Override 25 | public List getTypes() { 26 | return new ArrayList<>(); 27 | } 28 | 29 | @Override 30 | public Object readTag() { 31 | try { 32 | try { 33 | return NBTManager.getInstance().readCompressed(this.getObject()); 34 | } catch (Exception ignored) {} 35 | return PowerJSONParser.readCompressed(this.getObject()); 36 | } catch (FileNotFoundException e) { 37 | return null; 38 | } catch (IOException e) { 39 | throw new RuntimeException("can't read file",e); 40 | } catch (Exception e) { 41 | throw new RuntimeException("wrong format",e); 42 | } 43 | } 44 | 45 | @Override 46 | public void writeTagNBT(Object base) { 47 | NBTManager.getInstance().writeCompressed(this.getObject(), base); 48 | } 49 | 50 | @Override 51 | public void writeTagJSON(Object base) throws IOException { 52 | PowerJSONParser.writeCompressed(base, this.getObject()); 53 | } 54 | 55 | @Override 56 | protected Class getContainerClass() { 57 | return File.class; 58 | } 59 | 60 | @Override 61 | public String toString(){ 62 | return this.getObject().getName(); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/utils/Translator.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.utils; 2 | 3 | import me.dpohvar.powernbt.PowerNBT; 4 | import org.bukkit.Bukkit; 5 | import org.yaml.snakeyaml.Yaml; 6 | 7 | import java.io.File; 8 | import java.io.FileInputStream; 9 | import java.io.FileNotFoundException; 10 | import java.io.InputStream; 11 | import java.util.HashMap; 12 | import java.util.Map; 13 | import java.util.logging.Level; 14 | 15 | public class Translator { 16 | 17 | private Map tran = new HashMap(); 18 | 19 | public Translator(PowerNBT plugin, String locale) { 20 | if (locale.contains(File.separator)) throw new RuntimeException("locale name is not valid"); 21 | if (locale.equals("system")) locale = System.getProperty("user.language"); 22 | InputStream is = null; 23 | File file = new File(plugin.getLangFolder(), locale + ".yml"); 24 | if (!file.exists()) { 25 | is = plugin.getResource(locale + ".yml"); 26 | if (is == null) is = plugin.getResource("en.yml"); 27 | } else { 28 | try { 29 | is = new FileInputStream(file); 30 | } catch (FileNotFoundException ignored) { 31 | } 32 | } 33 | try { 34 | Yaml yaml = new Yaml(); 35 | Map map = yaml.load(is); 36 | Map vals = (Map) map.get("locale"); 37 | for (Map.Entry e : vals.entrySet()) { 38 | tran.put(e.getKey(), e.getValue().toString()); 39 | } 40 | } catch (Exception e) { 41 | Bukkit.getLogger().log(Level.WARNING, "Can not translate to "+locale, e); 42 | } 43 | } 44 | 45 | public String translate(String key, Object... values) { 46 | if (!tran.containsKey(key)) return "{" + key + "}"; 47 | return String.format(tran.get(key), values); 48 | } 49 | 50 | public String translate(String key) { 51 | if (!tran.containsKey(key)) return "{" + key + "}"; 52 | return tran.get(key); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/command/action/ActionBiLong.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.command.action; 2 | 3 | import me.dpohvar.powernbt.api.NBTManagerUtils; 4 | import me.dpohvar.powernbt.nbt.NBTContainer; 5 | import me.dpohvar.powernbt.nbt.NBTType; 6 | import me.dpohvar.powernbt.utils.Caller; 7 | import me.dpohvar.powernbt.utils.query.NBTQuery; 8 | 9 | import static me.dpohvar.powernbt.PowerNBT.plugin; 10 | 11 | public abstract class ActionBiLong extends Action { 12 | 13 | private final Caller caller; 14 | private final Argument arg1; 15 | private final Argument arg2; 16 | 17 | public ActionBiLong(Caller caller, String o1, String q1, String o2, String q2) { 18 | this.caller = caller; 19 | this.arg1 = new Argument(caller, o1, q1); 20 | this.arg2 = new Argument(caller, o2, q2); 21 | } 22 | 23 | @Override 24 | public void execute() throws Exception { 25 | if (arg1.needPrepare()) { 26 | arg1.prepare(this, null, null); 27 | return; 28 | } 29 | NBTContainer container1 = arg1.getContainer(); 30 | NBTQuery query1 = arg1.getQuery(); 31 | if (arg2.needPrepare()) { 32 | arg2.prepare(this, container1, query1); 33 | return; 34 | } 35 | Object base1 = container1.getCustomTag(query1); 36 | NBTContainer container2 = arg2.getContainer(); 37 | NBTQuery query2 = arg2.getQuery(); 38 | Object base2 = container2.getCustomTag(query2); 39 | if (!(base2 instanceof Number)){ 40 | throw new RuntimeException(plugin.translate("error_null")); 41 | } 42 | if (base1 == null) { 43 | base1 = NBTType.fromValue(base2).getDefaultValue(); 44 | } 45 | long baseValue = ((Number)base1).longValue(); 46 | long argValue = ((Number)base2).longValue(); 47 | Object result = NBTManagerUtils.convertValue(operation(baseValue, argValue), NBTType.fromValue(base1).type); 48 | container1.setCustomTag(query1, result); 49 | caller.sendValue(plugin.translate("success_edit"), result, false, false); 50 | 51 | } 52 | 53 | abstract long operation(long arg1, long arg2); 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/nbt/NBTContainerVariable.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.nbt; 2 | 3 | import me.dpohvar.powernbt.utils.Caller; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | public class NBTContainerVariable extends NBTContainer { 9 | 10 | Caller caller; 11 | String name; 12 | 13 | public NBTContainerVariable(Caller caller, String name) { 14 | super("%"+name); 15 | this.caller = caller; 16 | this.name = name; 17 | } 18 | 19 | 20 | public Caller getObject() { 21 | return this.caller; 22 | } 23 | 24 | @Override 25 | public List getTypes() { 26 | NBTContainer c = getContainer(); 27 | if (c == null) return new ArrayList<>(); 28 | return c.getTypes(); 29 | } 30 | 31 | public String getVariableName() { 32 | return name; 33 | } 34 | 35 | public NBTContainer getContainer() { 36 | return caller.getVariable(name); 37 | } 38 | 39 | public void setContainer(NBTContainer t) { 40 | caller.setVariable(name, t); 41 | } 42 | 43 | public void removeContainer() { 44 | caller.removeVariable(name); 45 | } 46 | 47 | @Override 48 | public Object readTag() { 49 | NBTContainer t = getContainer(); 50 | if (t != null) return t.readTag(); 51 | return null; 52 | } 53 | 54 | @Override 55 | public void writeTag(Object base) { 56 | NBTContainer t = getContainer(); 57 | if (t != null) t.writeTag(base); 58 | } 59 | 60 | @Override 61 | public void eraseTag() { 62 | caller.removeVariable(name); 63 | } 64 | 65 | @Override 66 | protected Object readCustomTag() { 67 | NBTContainer t = getContainer(); 68 | if (t != null) return t.readCustomTag(); 69 | return null; 70 | } 71 | 72 | @Override 73 | protected void writeCustomTag(Object base) { 74 | NBTContainer t = getContainer(); 75 | if (t == null) caller.setVariable(name, new NBTContainerValue(base)); 76 | else t.writeCustomTag(base); 77 | } 78 | 79 | @Override 80 | protected Class getContainerClass() { 81 | return Caller.class; 82 | } 83 | 84 | @Override 85 | public String toString() { 86 | return "%"+name; 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/command/action/ActionView.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.command.action; 2 | 3 | import me.dpohvar.powernbt.nbt.NBTContainer; 4 | import me.dpohvar.powernbt.utils.Caller; 5 | import me.dpohvar.powernbt.utils.query.NBTQuery; 6 | 7 | public class ActionView extends Action { 8 | 9 | private final Caller caller; 10 | private final Argument arg; 11 | private String[] args; 12 | 13 | private ActionView(Caller caller, String object, String query) { 14 | this.caller = caller; 15 | this.arg = new Argument(caller, object, query); 16 | } 17 | 18 | public ActionView(Caller caller, String object, String query, String args) { 19 | this(caller, object, query); 20 | if(args!=null) this.args = args.split(",|\\.|-"); 21 | } 22 | 23 | public ActionView(Caller caller, Argument arg, String args) { 24 | this.caller = caller; 25 | this.arg = arg; 26 | if(args!=null) this.args = args.split(",|\\.|-"); 27 | } 28 | 29 | @Override 30 | public void execute() throws Exception { 31 | if (arg.needPrepare()) { 32 | arg.prepare(this, null, null); 33 | return; 34 | } 35 | NBTContainer container = arg.getContainer(); 36 | NBTQuery query = arg.getQuery(); 37 | int start=-1, end=-1; 38 | boolean hex = false; 39 | boolean bin = false; 40 | if(args!=null) { 41 | for(String s:args){ 42 | if (s.equalsIgnoreCase("hex")||s.equalsIgnoreCase("h")) hex=true; 43 | else if (s.equalsIgnoreCase("bin")||s.equalsIgnoreCase("b")) bin=true; 44 | else if (s.equalsIgnoreCase("full")||s.equalsIgnoreCase("f")||s.equalsIgnoreCase("all")||s.equalsIgnoreCase("a")) { 45 | start=0; end=Integer.MAX_VALUE; 46 | } 47 | else if (s.matches("[0-9]+")){ 48 | if(end==-1) end = Integer.parseInt(s); 49 | else start = Integer.parseInt(s); 50 | } 51 | } 52 | } 53 | if(start==-1) start=0; 54 | if(end==-1) end=0; 55 | if(start>end){int t=start; start=end; end=t;}; 56 | caller.sendValueView("", container, query, start, end, hex, bin); 57 | } 58 | } 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/utils/viewer/ContainerControl.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.utils.viewer; 2 | 3 | import me.dpohvar.powernbt.nbt.NBTContainer; 4 | import me.dpohvar.powernbt.utils.query.NBTQuery; 5 | 6 | public class ContainerControl { 7 | 8 | private final NBTContainer container; 9 | private final NBTQuery query; 10 | private final boolean hasValue; 11 | private final Object value; 12 | private final String selector; 13 | private final NBTQuery accessQuery; 14 | private final boolean readonly; 15 | 16 | public ContainerControl(NBTContainer container, NBTQuery query, Object value){ 17 | this(container, query, true, value); 18 | } 19 | 20 | public ContainerControl(NBTContainer container, NBTQuery query){ 21 | this(container, query, false, null); 22 | } 23 | 24 | private ContainerControl(NBTContainer container, NBTQuery query, boolean hasValue, Object value){ 25 | this.container = container; 26 | this.query = query; 27 | this.hasValue = hasValue; 28 | this.value = value; 29 | this.selector = container.getSelector(); 30 | this.readonly = this.selector == null || container.isObjectReadonly(); 31 | NBTQuery containerSelectorQuery = container.getSelectorQuery(); 32 | if (this.readonly) { 33 | this.accessQuery = null; 34 | } else if (containerSelectorQuery != null) { 35 | this.accessQuery = containerSelectorQuery.join(query); 36 | } else { 37 | this.accessQuery = query; 38 | } 39 | } 40 | 41 | public NBTContainer getContainer() { 42 | return container; 43 | } 44 | 45 | public boolean hasValue() { 46 | return hasValue; 47 | } 48 | 49 | public NBTQuery getQuery() { 50 | return query; 51 | } 52 | 53 | public Object getValue() { 54 | return value; 55 | } 56 | 57 | public NBTQuery getAccessQuery() { 58 | return accessQuery; 59 | } 60 | 61 | public boolean isReadonly() { 62 | return readonly; 63 | } 64 | 65 | public String getSelector() { 66 | return selector; 67 | } 68 | 69 | public String getSelectorWithQuery() { 70 | if (this.selector == null) return null; 71 | return this.selector + " " + accessQuery; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/main/resources/en.yml: -------------------------------------------------------------------------------- 1 | lang: English 2 | version: 0.1 3 | author: DPOH-VAR 4 | 5 | locale: 6 | error_nochildren: "tag %s has no children nodes" 7 | error_noplayer: "player required" 8 | error_noentity: "no entity with id %d" 9 | error_nofile: "file %s not found" 10 | error_querynode: "invalid query format: %s" 11 | error_notenougharguments: "not enough arguments" 12 | error_noworld: "no world with name %s" 13 | error_parse: "can not parse %s to %s" 14 | error_parsetype: "can not parse object of type %s" 15 | error_playernotfound: "player %s not found" 16 | error_undefinedobject: "no nbt object %s" 17 | error_undefinedtype: "type of value %s not set" 18 | error_undefinedself: "object self not available in this context" 19 | error_toomanyarguments: "too many arguments" 20 | error_variablerequired: "variable required" 21 | error_null: "no value" 22 | error_parsevalue: "can not parse a value: %s" 23 | error_accessfile: "access denied to file %s" 24 | error_customfile: "wrong file name: %s" 25 | error_arraytype: "list types mismatch" 26 | error_index: "invalid index: %d" 27 | data_elements: "%d elements" 28 | data_null: "no data" 29 | data_unknown: "unknown type" 30 | data_bytes: "%d bytes" 31 | data_ints: "%d integers" 32 | data_emptyarray: "empty array" 33 | data_emptylist: "empty list" 34 | data_emptycompound: "empty compound" 35 | data_outofrange: "out of range" 36 | object_block: "block %s at %d:%d:%d:%s" 37 | request_select: "select a block or entity by right-click" 38 | success_removed: "removed: " 39 | success_copied: "copied to buffer: " 40 | success_select: "%s selected as %s" 41 | success_edit: "new value set: " 42 | success_debug_on: "debug mode is ON" 43 | success_debug_off: "debug mode is OFF" 44 | success_swap: "tags swapped" 45 | success_swap_null: "no elements to swap" 46 | success_move: "tag moved: " 47 | success_cut: "cutted: " 48 | success_rename: "tag renamed to %s: " 49 | success_add: "values added: " 50 | success_insert: "values added: " 51 | success_spawn: "entity %s spawned" 52 | fail_edit: "can not change value by query %s" 53 | fail_move: "can not move tag from %s" 54 | fail_rename: "can not rename tag" 55 | fail_add: "can not add tags" 56 | fail_insert: "can not insert tags" 57 | fail_spawn: "can't spawn entity" 58 | selection_cancel: "selection cancelled" 59 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/command/action/ActionMultiply.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.command.action; 2 | 3 | import me.dpohvar.powernbt.api.NBTManagerUtils; 4 | import me.dpohvar.powernbt.nbt.NBTContainer; 5 | import me.dpohvar.powernbt.nbt.NBTType; 6 | import me.dpohvar.powernbt.utils.Caller; 7 | import me.dpohvar.powernbt.utils.query.NBTQuery; 8 | 9 | import static me.dpohvar.powernbt.PowerNBT.plugin; 10 | 11 | public class ActionMultiply extends Action { 12 | 13 | private final Caller caller; 14 | private final Argument arg1; 15 | private final Argument arg2; 16 | 17 | public ActionMultiply(Caller caller, String o1, String q1, String o2, String q2) { 18 | this.caller = caller; 19 | this.arg1 = new Argument(caller, o1, q1); 20 | this.arg2 = new Argument(caller, o2, q2); 21 | } 22 | 23 | @Override 24 | public void execute() throws Exception { 25 | if (arg1.needPrepare()) { 26 | arg1.prepare(this, null, null); 27 | return; 28 | } 29 | NBTContainer container1 = arg1.getContainer(); 30 | NBTQuery query1 = arg1.getQuery(); 31 | if (arg2.needPrepare()) { 32 | arg2.prepare(this, container1, query1); 33 | return; 34 | } 35 | Object base1 = container1.getCustomTag(query1); 36 | NBTContainer container2 = arg2.getContainer(); 37 | NBTQuery query2 = arg2.getQuery(); 38 | Object base2 = container2.getCustomTag(query2); 39 | if (!(base2 instanceof Number number2)){ 40 | throw new RuntimeException(plugin.translate("error_null")); 41 | } 42 | if (base1 == null) base1 = NBTType.fromValue(base2).getDefaultValue(); 43 | Number mathResult; 44 | Number number1 = (Number) base1; 45 | if (number1 instanceof Float || number1 instanceof Double || number2 instanceof Float || number2 instanceof Double){ 46 | mathResult = number1.doubleValue() * number2.doubleValue(); 47 | } else { 48 | mathResult = number1.longValue() * number2.longValue(); 49 | } 50 | byte base1Type = NBTType.fromValue(base1).type; 51 | Object result = NBTManagerUtils.convertValue(mathResult, base1Type); 52 | container1.setCustomTag(query1, result); 53 | caller.sendValue(plugin.translate("success_edit"), result, false, false); 54 | 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/resources/config.yml: -------------------------------------------------------------------------------- 1 | debug: ${plugin-debug} 2 | lang: system 3 | 4 | ignore_set: 5 | block: 6 | - id 7 | - x 8 | - y 9 | - z 10 | entity: 11 | - id 12 | - UUID 13 | - UUIDMost 14 | - UUIDLeast 15 | - WorldUUIDLeast 16 | - WorldUUIDMost 17 | 18 | hooks: 19 | default: 20 | entity: 21 | getNBT: "net.minecraft.world.entity.Entity d(net.minecraft.nbt.NBTTagCompound): boolean" 22 | getNBTSimple: "net.minecraft.world.entity.Entity save(net.minecraft.nbt.NBTTagCompound): net.minecraft.nbt.NBTTagCompound" 23 | setNBT: "net.minecraft.world.entity.Entity load(net.minecraft.nbt.NBTTagCompound): void" 24 | getHandle: "{cb}.entity.CraftEntity *(): net.minecraft.world.entity.Entity" 25 | createType: "net.minecraft.world.entity.EntityTypes public static *(net.minecraft.nbt.NBTTagCompound, net.minecraft.world.level.World): java.util.Optional" 26 | getBukkitEntity: "net.minecraft.world.entity.Entity *(): {cb}.entity.CraftEntity" 27 | block: 28 | getSnapshot: "{cb}.block.CraftBlockEntityState getSnapshot()" 29 | getNBT: "net.minecraft.world.level.block.entity.TileEntity save(net.minecraft.nbt.NBTTagCompound): net.minecraft.nbt.NBTTagCompound" 30 | setNBT: "net.minecraft.world.level.block.entity.TileEntity load(net.minecraft.nbt.NBTTagCompound): void" 31 | item: 32 | handle: "{cb}.inventory.CraftItemStack *:net.minecraft.world.item.ItemStack" 33 | craftCopy: "{cb}.inventory.CraftItemStack static *(org.bukkit.inventory.ItemStack): {cb}.inventory.CraftItemStack" 34 | getNBT: "net.minecraft.world.item.ItemStack *(net.minecraft.nbt.NBTTagCompound): net.minecraft.nbt.NBTTagCompound" 35 | setNBT: "net.minecraft.world.item.ItemStack declared load(net.minecraft.nbt.NBTTagCompound): void" 36 | world: 37 | getHandle: "{cb}.CraftWorld *(): net.minecraft.server.level.WorldServer" 38 | addEntity: "net.minecraft.server.level.WorldServer addEntity(net.minecraft.world.entity.Entity, org.bukkit.event.entity.CreatureSpawnEvent$SpawnReason): boolean" 39 | 1_18_1-R0_1-SNAPSHOT: 40 | entity: 41 | getNBTSimple: "net.minecraft.world.entity.Entity f(net.minecraft.nbt.NBTTagCompound): net.minecraft.nbt.NBTTagCompound" 42 | setNBT: "net.minecraft.world.entity.Entity g(net.minecraft.nbt.NBTTagCompound): void" 43 | block: 44 | getNBT: "net.minecraft.world.level.block.entity.TileEntity m(): net.minecraft.nbt.NBTTagCompound" 45 | setNBT: "net.minecraft.world.level.block.entity.TileEntity a(net.minecraft.nbt.NBTTagCompound): void" -------------------------------------------------------------------------------- /src/main/resources/ru.yml: -------------------------------------------------------------------------------- 1 | lang: Русский 2 | version: 0.1 3 | author: DPOH-VAR 4 | 5 | locale: 6 | error_nochildren: "элемент %s не имеет дочерних элементов" 7 | error_noplayer: "доступно только игрокам" 8 | error_noentity: "ничего нет с id %d" 9 | error_nofile: "файл %s не найден" 10 | error_querynode: "неверный формат запроса: %s" 11 | error_notenougharguments: "недостаточно параметров" 12 | error_noworld: "мир %s не существует" 13 | error_parse: "невозможно привести %s к типу %s" 14 | error_parsetype: "невозможно получить значение типа %s" 15 | error_playernotfound: "игрок %s не найден" 16 | error_undefinedobject: "объект %s не определен" 17 | error_undefinedtype: "не указан тип значения %s" 18 | error_undefinedself: "объект self не может быть использован в этом случае" 19 | error_toomanyarguments: "слишком много параметров" 20 | error_variablerequired: "необходимо указать переменную" 21 | error_arraytype: "тип списка не совпадает с типом данных" 22 | error_index: "неверный индекс: %d" 23 | error_null: "нет значения" 24 | error_parsevalue: "неверно указано значение: %s" 25 | error_accessfile: "доступ к файлу %s запрещен" 26 | error_customfile: "неверно указано имя файла: %s" 27 | data_elements: "%d элементов" 28 | data_null: "пусто" 29 | data_unknown: "неизвестный тип" 30 | data_bytes: "%d байт" 31 | data_ints: "%d чисел" 32 | data_emptyarray: "пустой массив" 33 | data_emptylist: "пустой список" 34 | data_emptycompound: "пустой узел" 35 | data_outofrange: "вне диапазона" 36 | object_block: "блок %s на %d:%d:%d:%s" 37 | request_select: "выделите объект или блок правой кнопкой мыши" 38 | success_removed: "удалено: " 39 | success_copied: "скопировано в буфер: " 40 | success_select: "%s выбран как %s" 41 | success_edit: "тег установлен: " 42 | success_debug_on: "дебажим" 43 | success_debug_off: "не дебажим" 44 | success_swap: "теги свопнулись" 45 | success_swap_null: "нет элементов для свопа" 46 | success_move: "перемещено: " 47 | success_cut: "вырезано: " 48 | success_rename: "тег переименован в %s: " 49 | success_add: "добавлены значения: " 50 | success_insert: "добавлены значения: " 51 | success_spawn: "создан: %s" 52 | fail_edit: "невозможно изменить значение по запросу %s" 53 | fail_move: "невозможно переместить значение из %s" 54 | fail_rename: "невозможно переименовать тег" 55 | fail_add: "невозможно добавить теги" 56 | fail_insert: "невозможно вставить теги" 57 | fail_spawn: "невозможно создать энтити" 58 | selection_cancel: "выбор объекта отменен" -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/command/action/ActionInsert.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.command.action; 2 | 3 | import me.dpohvar.powernbt.PowerNBT; 4 | import me.dpohvar.powernbt.api.NBTList; 5 | import me.dpohvar.powernbt.api.NBTManagerUtils; 6 | import me.dpohvar.powernbt.nbt.NBTContainer; 7 | import me.dpohvar.powernbt.nbt.NBTType; 8 | import me.dpohvar.powernbt.utils.Caller; 9 | import me.dpohvar.powernbt.utils.query.NBTQuery; 10 | 11 | import java.util.Arrays; 12 | import java.util.List; 13 | 14 | public class ActionInsert extends Action { 15 | 16 | private final Caller caller; 17 | private final Argument arg1; 18 | private final Argument arg2; 19 | private final int pos; 20 | 21 | public ActionInsert(Caller caller, String o1, String q1, String pos, String o2, String q2) { 22 | this.caller = caller; 23 | this.pos = Integer.parseInt(pos); 24 | if(this.pos<0) caller.send(PowerNBT.plugin.translate("error_index",this.pos)); 25 | this.arg1 = new Argument(caller, o1, q1); 26 | this.arg2 = new Argument(caller, o2, q2); 27 | } 28 | 29 | @Override 30 | public void execute() throws Exception { 31 | if (arg1.needPrepare()) { 32 | arg1.prepare(this, null, null); 33 | return; 34 | } 35 | NBTContainer container1 = arg1.getContainer(); 36 | NBTQuery query1 = arg1.getQuery(); 37 | if (arg2.needPrepare()) { 38 | arg2.prepare(this, container1, query1); 39 | return; 40 | } 41 | Object base1 = container1.getCustomTag(query1); 42 | NBTContainer container2 = arg2.getContainer(); 43 | NBTQuery query2 = arg2.getQuery(); 44 | Object base2 = container2.getCustomTag(query2); 45 | if (base1 instanceof NBTList list){ 46 | list.add(pos,base2); 47 | container1.setCustomTag(query1,list); 48 | caller.sendValue(PowerNBT.plugin.translate("success_insert"), base2, false, false); 49 | } else if (base1 != null && base1.getClass().isArray() && base2 instanceof Number num){ 50 | byte type = NBTType.fromValue(base1).type; 51 | Object[] array = NBTManagerUtils.convertToObjectArrayOrNull(base1); 52 | List list = Arrays.asList(array); 53 | list.add(pos, num); 54 | Object result = NBTManagerUtils.convertValue(list, type); 55 | container1.setCustomTag(query1, result); 56 | caller.sendValue(PowerNBT.plugin.translate("success_add"), num, false, false); 57 | } else { 58 | caller.send(PowerNBT.plugin.translate("fail_insert")); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/nbt/NBTContainerEntity.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.nbt; 2 | 3 | import me.dpohvar.powernbt.api.NBTCompound; 4 | import me.dpohvar.powernbt.api.NBTManager; 5 | import me.dpohvar.powernbt.utils.ReflectionUtils; 6 | import org.bukkit.entity.Entity; 7 | import org.bukkit.entity.LivingEntity; 8 | import org.bukkit.entity.Player; 9 | 10 | import java.util.ArrayList; 11 | import java.util.List; 12 | import java.util.Map; 13 | import java.util.Objects; 14 | 15 | public class NBTContainerEntity extends NBTContainer { 16 | 17 | Entity entity; 18 | 19 | public NBTContainerEntity(Entity entity) { 20 | super("id"+entity.getEntityId()); 21 | this.entity = entity; 22 | } 23 | 24 | public Entity getObject() { 25 | return entity; 26 | } 27 | 28 | @Override 29 | public List getTypes() { 30 | List s = new ArrayList<>(); 31 | s.add("entity"); 32 | if (entity instanceof LivingEntity) s.add("living"); 33 | //noinspection deprecation 34 | s.add(entity.getType().getName()); 35 | return s; 36 | } 37 | 38 | @Override 39 | public NBTCompound readTag() { 40 | NBTCompound tag = NBTManager.getInstance().read(entity); 41 | if (ReflectionUtils.isForge()) { 42 | NBTCompound nbtCompound = NBTManager.getInstance().readForgeData(entity); 43 | tag.put("ForgeData", Objects.requireNonNullElseGet(nbtCompound, NBTCompound::new)); 44 | } 45 | return tag; 46 | } 47 | 48 | @Override 49 | protected void eraseTag() { 50 | if (!(entity instanceof Player)) entity.remove(); 51 | } 52 | 53 | @Override 54 | public void writeTag(Object value) { 55 | NBTCompound compound = null; 56 | if (value instanceof NBTCompound c) compound = c; 57 | else if (value instanceof Map map) compound = new NBTCompound(map); 58 | if (compound == null) return; 59 | NBTManager.getInstance().write(entity, compound); 60 | if (ReflectionUtils.isForge()){ 61 | Object forgeData = compound.get("ForgeData"); 62 | if (forgeData instanceof NBTCompound forgeCompound) 63 | NBTManager.getInstance().writeForgeData(entity, forgeCompound); 64 | } 65 | } 66 | 67 | @Override 68 | protected Class getContainerClass() { 69 | return Entity.class; 70 | } 71 | 72 | @Override 73 | public String toString(){ 74 | return entity.getName(); 75 | } 76 | 77 | @Override 78 | public String getSelector() { 79 | return "id"+entity.getEntityId(); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/command/action/ActionSpawn.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.command.action; 2 | 3 | import me.dpohvar.powernbt.api.NBTCompound; 4 | import me.dpohvar.powernbt.api.NBTManager; 5 | import me.dpohvar.powernbt.nbt.NBTContainer; 6 | import me.dpohvar.powernbt.utils.Caller; 7 | import me.dpohvar.powernbt.utils.query.NBTQuery; 8 | import org.bukkit.Bukkit; 9 | import org.bukkit.World; 10 | import org.bukkit.command.BlockCommandSender; 11 | import org.bukkit.command.CommandSender; 12 | import org.bukkit.entity.Entity; 13 | 14 | import java.util.Map; 15 | 16 | import static me.dpohvar.powernbt.PowerNBT.plugin; 17 | 18 | public class ActionSpawn extends Action { 19 | 20 | private final Caller caller; 21 | private final Argument arg; 22 | private String worldParam; 23 | 24 | private ActionSpawn(Caller caller, String object, String query) { 25 | this.caller = caller; 26 | this.arg = new Argument(caller, object, query); 27 | } 28 | 29 | public ActionSpawn(Caller caller, String object, String query, String worldParam) { 30 | this(caller, object, query); 31 | this.worldParam = worldParam; 32 | } 33 | 34 | @Override 35 | public void execute() throws Exception { 36 | if (arg.needPrepare()) { 37 | arg.prepare(this, null, null); 38 | return; 39 | } 40 | NBTContainer container = arg.getContainer(); 41 | NBTQuery query = arg.getQuery(); 42 | World world; 43 | if (worldParam == null) { 44 | CommandSender owner = caller.getOwner(); 45 | if (owner instanceof Entity) world = ((Entity) owner).getWorld(); 46 | else if (owner instanceof BlockCommandSender) world = ((BlockCommandSender) owner).getBlock().getWorld(); 47 | else throw new RuntimeException(plugin.translate("error_noplayer")); 48 | } else { 49 | world = Bukkit.getWorld(worldParam); 50 | if (world == null) throw new RuntimeException(plugin.translate("error_noworld", worldParam)); 51 | } 52 | Object base = container.getCustomTag(query); 53 | 54 | NBTCompound compound = null; 55 | if (base instanceof NBTCompound c) compound = c; 56 | else if (base instanceof Map map) compound = new NBTCompound(map); 57 | 58 | if (compound != null) { 59 | Entity entity = NBTManager.getInstance().spawnEntity(compound, world); 60 | if (entity != null) { 61 | caller.send(plugin.translate("success_spawn", entity.getName())); 62 | return; 63 | } 64 | } 65 | caller.send(plugin.translate("error_parsevalue", "")); 66 | } 67 | } 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/utils/query/KeySelector.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.utils.query; 2 | 3 | import me.dpohvar.powernbt.api.NBTCompound; 4 | import me.dpohvar.powernbt.exception.NBTTagNotFound; 5 | import me.dpohvar.powernbt.utils.StringParser; 6 | import org.bukkit.ChatColor; 7 | 8 | import java.util.*; 9 | 10 | public record KeySelector(String key) implements QSelector { 11 | 12 | @Override 13 | public Object get(Object current, boolean useDefault) throws NBTTagNotFound { 14 | if (useDefault && current == null) return null; 15 | if (current instanceof Map map) { 16 | if (!map.containsKey(key)) { 17 | if (useDefault) return null; 18 | throw new NBTTagNotFound(current, this.toString()); 19 | } 20 | return map.get(key); 21 | } 22 | throw new NBTTagNotFound(current, this.toString()); 23 | } 24 | 25 | @Override 26 | public Object delete(Object current) throws NBTTagNotFound { 27 | if (current instanceof Map map) { 28 | if (!map.containsKey(key)) throw new NBTTagNotFound(current, this.toString()); 29 | Map resultMap = cloneMap(map); 30 | resultMap.remove(key); 31 | return resultMap; 32 | } 33 | throw new NBTTagNotFound(current, this.toString()); 34 | } 35 | 36 | @Override 37 | public Object set(Object current, Object value, boolean createDir) throws NBTTagNotFound { 38 | if (current == null && createDir) current = new HashMap<>(); 39 | if (current instanceof Map map) { 40 | Object prevValue = map.get(key); 41 | if (map.containsKey(key) && Objects.equals(prevValue, value)) return map; 42 | Map resultMap = cloneMap(map); 43 | resultMap.put(key, value); 44 | return resultMap; 45 | } 46 | throw new NBTTagNotFound(current, this.toString()); 47 | } 48 | 49 | private static Map cloneMap(Map map){ 50 | if (map instanceof NBTCompound c) return c.clone(); 51 | return new HashMap<>(map); 52 | } 53 | 54 | @Override 55 | public String getSeparator(QSelector prevSelector) { 56 | if (prevSelector == null) return null; 57 | if (prevSelector instanceof StringAsJsonSelector) return null; 58 | return "."; 59 | } 60 | 61 | private static final Set badKeys = new HashSet<>(Arrays.asList("copy","rm","rem","remove","remame","paste","add","cut","set","select","as","view","debug","cancel","swap","insert","ins","spawn")); 62 | @Override 63 | public String toString() { 64 | if (key.isEmpty()) return StringParser.wrapToQuotes(key); 65 | if (badKeys.contains(key)) return StringParser.wrapToQuotes(key); 66 | if (key.matches("[\\[\\].(){}#*\\s]")) return StringParser.wrapToQuotes(key); 67 | if (!ChatColor.stripColor(key).equals(key)) return StringParser.wrapToQuotes(key); 68 | return key; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/nbt/NBTContainerBlock.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.nbt; 2 | 3 | import me.dpohvar.powernbt.api.NBTCompound; 4 | import me.dpohvar.powernbt.api.NBTManager; 5 | import me.dpohvar.powernbt.utils.StringParser; 6 | import org.bukkit.Material; 7 | import org.bukkit.block.Block; 8 | import org.bukkit.block.BlockState; 9 | import org.bukkit.block.TileState; 10 | 11 | import java.util.Arrays; 12 | import java.util.List; 13 | import java.util.Map; 14 | 15 | import static me.dpohvar.powernbt.PowerNBT.plugin; 16 | 17 | public class NBTContainerBlock extends NBTContainer { 18 | 19 | Block block; 20 | 21 | public NBTContainerBlock(Block block) { 22 | super(block.getX()+":"+block.getY()+":"+block.getZ()+":"+StringParser.wrapToQuotesIfNeeded(block.getWorld().getName())); 23 | this.block = block; 24 | } 25 | 26 | public Block getObject() { 27 | return block; 28 | } 29 | 30 | @Override 31 | public List getTypes() { 32 | return Arrays.asList("block", "block_" + block.getType().name()); 33 | } 34 | 35 | @Override 36 | public NBTCompound readCustomTag() { 37 | NBTCompound tag = readTag(); 38 | if (tag!=null) { 39 | List ignores = plugin.getConfig().getStringList("ignore_get.block"); 40 | for (String s:ignores) tag.remove(s); 41 | } 42 | return tag; 43 | } 44 | 45 | @Override 46 | protected void eraseTag() { 47 | block.setBlockData(Material.AIR.createBlockData()); 48 | } 49 | 50 | public NBTCompound readTag() { 51 | return NBTManager.getInstance().read(block); 52 | } 53 | 54 | @Override 55 | public void writeTag(Object value) { 56 | BlockState state = block.getState(); 57 | if (state instanceof TileState tile && value instanceof NBTCompound compound) { 58 | NBTManager.getInstance().write(tile, compound); 59 | state.update(); 60 | } 61 | } 62 | 63 | @Override 64 | public void writeCustomTag(Object value) { 65 | NBTCompound compound = null; 66 | if (value == null) compound = new NBTCompound(); 67 | if (value instanceof NBTCompound c) compound = c; 68 | else if (value instanceof Map map) compound = new NBTCompound(map); 69 | if (compound == null) return; 70 | compound = compound.clone(); 71 | List ignores = plugin.getConfig().getStringList("ignore_set.block"); 72 | for (String s:ignores) compound.remove(s); 73 | NBTCompound original = readTag(); 74 | if(compound.get("x")==null) compound.put("x",original.get("x")); 75 | if(compound.get("y")==null) compound.put("y",original.get("y")); 76 | if(compound.get("z")==null) compound.put("z",original.get("z")); 77 | writeTag(compound); 78 | } 79 | 80 | @Override 81 | protected Class getContainerClass() { 82 | return Block.class; 83 | } 84 | 85 | @Override 86 | public String toString(){ 87 | return block.getBlockData().getMaterial().name(); 88 | } 89 | 90 | } 91 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/nbt/NBTContainerFile.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.nbt; 2 | 3 | import me.dpohvar.powernbt.api.NBTManager; 4 | import me.dpohvar.powernbt.utils.PowerJSONParser; 5 | import me.dpohvar.powernbt.utils.StringParser; 6 | 7 | import java.io.*; 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | 11 | public class NBTContainerFile extends NBTContainer { 12 | 13 | private final File file; 14 | 15 | public NBTContainerFile(File file) { 16 | this(file, null); 17 | } 18 | 19 | public NBTContainerFile(File file, String selector) { 20 | super(selector == null ? "file:"+ StringParser.wrapToQuotesIfNeeded(file.toString()) : selector); 21 | this.file = file; 22 | } 23 | 24 | public File getObject() { 25 | return file; 26 | } 27 | 28 | @Override 29 | public Object readTag() { 30 | 31 | boolean isNBT; 32 | if (!file.exists() || file.isDirectory()) return null; 33 | try (var input = getDataInputStream()) { 34 | byte b = input.readByte(); 35 | NBTType nbtType = NBTType.fromByte(b); 36 | isNBT = (nbtType != null); 37 | } catch (FileNotFoundException e) { 38 | throw new RuntimeException("no file",e); 39 | } catch (IOException e) { 40 | throw new RuntimeException("can't read file",e); 41 | } 42 | 43 | try { 44 | if (isNBT) return NBTManager.getInstance().read(file); 45 | else return PowerJSONParser.read(file); 46 | } catch (FileNotFoundException e) { 47 | return null; 48 | } catch (IOException e) { 49 | throw new RuntimeException("can't read file",e); 50 | } catch (Exception e) { 51 | throw new RuntimeException("wrong format",e); 52 | } 53 | } 54 | 55 | protected DataInputStream getDataInputStream() throws FileNotFoundException { 56 | return new DataInputStream(new FileInputStream(file)); 57 | } 58 | 59 | protected final boolean isNBT(Object base){ 60 | return NBTType.fromValueOrNull(base) != null; 61 | } 62 | 63 | @Override 64 | public void writeTag(Object base) { 65 | try { 66 | if (isNBT(base)) { 67 | writeTagNBT(base); 68 | } else { 69 | writeTagJSON(base); 70 | } 71 | } catch (FileNotFoundException e) { 72 | throw new RuntimeException("file "+file+" not found", e); 73 | } catch (Exception e) { 74 | throw new RuntimeException("can't write to file", e); 75 | } 76 | } 77 | 78 | public void writeTagNBT(Object base) throws Exception{ 79 | NBTManager.getInstance().write(file, base); 80 | } 81 | 82 | public void writeTagJSON(Object base) throws IOException{ 83 | PowerJSONParser.write(base, file); 84 | } 85 | 86 | @Override 87 | public List getTypes() { 88 | return new ArrayList<>(); 89 | } 90 | 91 | @Override 92 | public void eraseTag() { 93 | file.delete(); 94 | } 95 | 96 | @Override 97 | protected Class getContainerClass() { 98 | return File.class; 99 | } 100 | 101 | @Override 102 | public String toString(){ 103 | return file.getName(); 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/utils/viewer/components/ListElement.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.utils.viewer.components; 2 | 3 | import me.dpohvar.powernbt.utils.query.IndexSelector; 4 | import me.dpohvar.powernbt.utils.viewer.ContainerControl; 5 | import me.dpohvar.powernbt.utils.viewer.DisplayValueHelper; 6 | import me.dpohvar.powernbt.utils.viewer.EventBuilder; 7 | import me.dpohvar.powernbt.utils.viewer.ViewerStyle; 8 | import net.md_5.bungee.api.ChatColor; 9 | import net.md_5.bungee.api.chat.BaseComponent; 10 | import net.md_5.bungee.api.chat.TextComponent; 11 | 12 | import java.util.List; 13 | 14 | public class ListElement implements Element { 15 | 16 | private final TextComponent component; 17 | 18 | public ListElement(ViewerStyle style, ContainerControl control, List list, int start, int end, int limitCol, int limitRow, boolean hex, boolean bin){ 19 | this.component = getValuesComponent(style, control, list, start, end, limitCol, limitRow, hex, bin); 20 | } 21 | 22 | private static TextComponent getValuesComponent(ViewerStyle style, ContainerControl control, List list, int start, int end, int limitCol, int limitRow, boolean hex, boolean bin){ 23 | int toEnd = end; 24 | if (start == 0 && toEnd == 0) toEnd = limitCol; 25 | if (list.size() == 0) { 26 | return new TextComponent("empty"); 27 | } 28 | TextComponent component = new TextComponent(""); 29 | 30 | boolean readonly = control.isReadonly(); 31 | for (int i = start; i < Math.min(toEnd, list.size()); i++) { 32 | Object listValue = list.get(i); 33 | IndexSelector indexSelector = new IndexSelector(i); 34 | if (readonly) { 35 | StringBuilder builder = new StringBuilder(); 36 | if (i != start) builder.append("\n").append(ChatColor.RESET); 37 | builder.append(style.getColorByValue(listValue)).append(indexSelector).append(": "); 38 | component.addExtra(builder.toString()); 39 | } else { 40 | InteractiveElement keyNameElement = new InteractiveElement( 41 | style.getColorByValue(listValue), 42 | indexSelector.toString(), 43 | EventBuilder.runNbt(control.getSelector() + " " + control.getAccessQuery().add(indexSelector), false), 44 | EventBuilder.popup("select " + i), 45 | null 46 | ); 47 | if (i != start) component.addExtra("\n"); 48 | component.addExtra(keyNameElement.getComponent()); 49 | component.addExtra(": "); 50 | } 51 | // VALUE 52 | String shortValue = DisplayValueHelper.getShortValue(style, listValue, limitRow, hex, bin); 53 | if (ChatColor.stripColor(shortValue).isEmpty()) shortValue+=" "; 54 | if (readonly) { 55 | component.addExtra(shortValue); 56 | } else { 57 | InteractiveElement ValueElement = new InteractiveElement( 58 | null, 59 | shortValue, 60 | EventBuilder.suggestNbt(control.getSelector() + " " + control.getAccessQuery().add(indexSelector) + " = ", false), 61 | EventBuilder.popup("edit"), 62 | null 63 | ); 64 | component.addExtra(ValueElement.getComponent()); 65 | } 66 | } 67 | return component; 68 | 69 | } 70 | 71 | @Override 72 | public BaseComponent getComponent() { 73 | return component; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/listener/SelectListener.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.listener; 2 | 3 | import me.dpohvar.powernbt.PowerNBT; 4 | import me.dpohvar.powernbt.command.action.Action; 5 | import me.dpohvar.powernbt.command.action.Argument; 6 | import me.dpohvar.powernbt.nbt.NBTContainerBlock; 7 | import me.dpohvar.powernbt.nbt.NBTContainerEntity; 8 | import me.dpohvar.powernbt.nbt.NBTContainerItem; 9 | import me.dpohvar.powernbt.utils.Caller; 10 | import org.bukkit.GameMode; 11 | import org.bukkit.Material; 12 | import org.bukkit.block.Block; 13 | import org.bukkit.entity.Entity; 14 | import org.bukkit.entity.HumanEntity; 15 | import org.bukkit.entity.Player; 16 | import org.bukkit.event.EventHandler; 17 | import org.bukkit.event.Listener; 18 | import org.bukkit.event.inventory.InventoryClickEvent; 19 | import org.bukkit.event.player.PlayerInteractEntityEvent; 20 | import org.bukkit.event.player.PlayerInteractEvent; 21 | import org.bukkit.inventory.ItemStack; 22 | 23 | /** 24 | * Created by DPOH-VAR 25 | * 20.12.13 2:05. 26 | */ 27 | public class SelectListener implements Listener { 28 | 29 | 30 | 31 | @EventHandler 32 | public void block(PlayerInteractEvent event) { 33 | if (!event.getAction().equals(org.bukkit.event.block.Action.RIGHT_CLICK_BLOCK)) return; 34 | Player player = event.getPlayer(); 35 | Caller caller = PowerNBT.plugin.getCaller(player); 36 | try { 37 | Argument argument = caller.getArgument(); 38 | Action action = caller.getAction(); 39 | if (argument == null || action == null) return; 40 | if (!player.isSneaking()) caller.hold(null,null); 41 | Block b = event.getClickedBlock(); 42 | argument.select(new NBTContainerBlock(b)); 43 | action.execute(); 44 | event.setCancelled(true); 45 | } catch (Throwable t) { 46 | caller.handleException(t); 47 | } 48 | } 49 | 50 | @EventHandler 51 | public void entity(PlayerInteractEntityEvent event) { 52 | Player player = event.getPlayer(); 53 | Caller caller = PowerNBT.plugin.getCaller(player); 54 | try { 55 | Argument argument = caller.getArgument(); 56 | Action action = caller.getAction(); 57 | if (argument == null || action == null) return; 58 | if (!player.isSneaking()) caller.hold(null,null); 59 | Entity e = event.getRightClicked(); 60 | argument.select(new NBTContainerEntity(e)); 61 | action.execute(); 62 | event.setCancelled(true); 63 | } catch (Throwable t) { 64 | caller.handleException(t); 65 | } 66 | } 67 | 68 | @EventHandler 69 | public void inventory(InventoryClickEvent event) { 70 | GameMode gm = event.getWhoClicked().getGameMode(); 71 | if (event.isRightClick() && gm == GameMode.CREATIVE) return; 72 | ItemStack cursor = event.getCursor(); 73 | if (cursor!=null && !cursor.getType().equals(Material.AIR)) return; 74 | ItemStack item = event.getCurrentItem(); 75 | if (item==null || item.getType().equals(Material.AIR)) return; 76 | HumanEntity human = event.getWhoClicked(); 77 | if (!(human instanceof Player)) return; 78 | Player player = (Player) human; 79 | Caller caller = PowerNBT.plugin.getCaller(player); 80 | try { 81 | Argument argument = caller.getArgument(); 82 | Action action = caller.getAction(); 83 | if (argument == null || action == null) return; 84 | if (!event.isShiftClick()) caller.hold(null,null); 85 | argument.select(new NBTContainerItem(item)); 86 | action.execute(); 87 | event.setCancelled(true); 88 | } catch (Throwable t) { 89 | caller.handleException(t); 90 | } 91 | } 92 | 93 | } 94 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/utils/viewer/InteractiveViewer.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.utils.viewer; 2 | 3 | import me.dpohvar.powernbt.api.NBTManagerUtils; 4 | import me.dpohvar.powernbt.exception.NBTTagNotFound; 5 | import me.dpohvar.powernbt.nbt.NBTContainer; 6 | import me.dpohvar.powernbt.utils.query.NBTQuery; 7 | import me.dpohvar.powernbt.utils.viewer.components.FooterElement; 8 | import me.dpohvar.powernbt.utils.viewer.components.ListElement; 9 | import me.dpohvar.powernbt.utils.viewer.components.MapElement; 10 | import me.dpohvar.powernbt.utils.viewer.components.NavbarElement; 11 | import net.md_5.bungee.api.chat.TextComponent; 12 | 13 | import java.util.Arrays; 14 | import java.util.Map; 15 | 16 | public class InteractiveViewer { 17 | 18 | private ViewerStyle style; 19 | private int colLimit; 20 | private int rowLimit; 21 | 22 | public InteractiveViewer(ViewerStyle viewerStyle, int rowLimit, int colLimit){ 23 | this.style = viewerStyle; 24 | this.colLimit = colLimit; 25 | this.rowLimit = rowLimit; 26 | } 27 | 28 | public void setStyle(ViewerStyle viewerStyle) { 29 | this.style = viewerStyle; 30 | } 31 | 32 | public String getShortValue(Object base, boolean hex, boolean bin){ 33 | return DisplayValueHelper.getShortValue(style, base, rowLimit, hex, bin); 34 | } 35 | 36 | public TextComponent getFullValue(final NBTContainer container, final NBTQuery query, int start, int end, final boolean hex, final boolean bin) throws NBTTagNotFound { 37 | TextComponent result = new TextComponent(); 38 | 39 | ContainerControl control; 40 | try { 41 | Object value = container.getCustomTag(query); 42 | control = new ContainerControl(container, query, value); 43 | } catch (NBTTagNotFound error) { 44 | control = new ContainerControl(container, query); 45 | } 46 | 47 | NavbarElement navbarElement = new NavbarElement(style, control); 48 | result.addExtra(navbarElement.getComponent()); 49 | if (control.hasValue()) { 50 | Object value = control.getValue(); 51 | result.addExtra(topSeparator()); 52 | if (value instanceof Map map) { 53 | MapElement mapElement = new MapElement(style, control, map, start, end, colLimit, rowLimit, hex, bin); 54 | result.addExtra(mapElement.getComponent()); 55 | } else if (value instanceof String s) { 56 | result.addExtra(DisplayValueHelper.getStringValue(style, s, start, end, colLimit*rowLimit, hex)); 57 | } else { 58 | Object[] objects = NBTManagerUtils.convertToObjectArrayOrNull(value); 59 | if (objects != null) { 60 | ListElement listElement = new ListElement(style, control, Arrays.asList(objects), start, end, colLimit, rowLimit, hex, bin); 61 | result.addExtra(listElement.getComponent()); 62 | } else { 63 | result.addExtra(DisplayValueHelper.getShortValue(style, value, rowLimit, hex, bin)); 64 | } 65 | } 66 | } 67 | result.addExtra(bottomSeparator()); 68 | 69 | FooterElement footerElement = new FooterElement(style, control, colLimit, rowLimit, start, end, hex, bin); 70 | result.addExtra(footerElement.getComponent()); 71 | 72 | return result; 73 | } 74 | 75 | private TextComponent topSeparator(){ 76 | TextComponent component = new TextComponent("\n" + style.getIcon("lineTopSeparator") + "\n"); 77 | component.setColor(style.getColor("lineTopSeparator")); 78 | return component; 79 | } 80 | 81 | private TextComponent bottomSeparator(){ 82 | TextComponent component = new TextComponent("\n" + style.getIcon("lineBottomSeparator") + "\n"); 83 | component.setColor(style.getColor("lineBottomSeparator")); 84 | return component; 85 | } 86 | 87 | } 88 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/utils/viewer/ViewerStyle.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.utils.viewer; 2 | 3 | import net.md_5.bungee.api.ChatColor; 4 | import org.bukkit.configuration.ConfigurationSection; 5 | import org.jetbrains.annotations.NotNull; 6 | 7 | import java.util.Collection; 8 | import java.util.HashMap; 9 | import java.util.List; 10 | import java.util.Map; 11 | import java.util.stream.Collectors; 12 | 13 | public class ViewerStyle { 14 | private ConfigurationSection colorConfig; 15 | private ConfigurationSection iconConfig; 16 | private final ChatColor defaultColor = ChatColor.WHITE; 17 | private final Map colors = new HashMap<>(); 18 | private final Map> colorLists = new HashMap<>(); 19 | private final Map icons = new HashMap<>(); 20 | 21 | public ViewerStyle(ConfigurationSection colorConfig, ConfigurationSection iconConfig){ 22 | this.colorConfig = colorConfig; 23 | this.iconConfig = iconConfig; 24 | } 25 | 26 | public ChatColor getColor(String key){ 27 | if (colors.containsKey(key)) return colors.get(key); 28 | String colorDescription = colorConfig.getString(key); 29 | ChatColor color; 30 | if (colorDescription == null) color = defaultColor; 31 | else color = ChatColor.of(colorDescription); 32 | colors.put(key, color); 33 | return color; 34 | } 35 | 36 | public ChatColor getColorMod(String key, int index){ 37 | if (colorLists.containsKey(key)) { 38 | List colors = colorLists.get(key); 39 | if (colors.size() == 0) return defaultColor; 40 | return colors.get(index % colors.size()); 41 | } 42 | List colorDescriptions = colorConfig.getStringList(key); 43 | List colors = colorDescriptions.stream().map(colorDescription -> { 44 | if (colorDescription == null) return defaultColor; 45 | return ChatColor.of(colorDescription); 46 | }).toList(); 47 | this.colorLists.put(key, colors); 48 | if (colors.size() == 0) return defaultColor; 49 | return colors.get(index % colors.size()); 50 | } 51 | 52 | public String getIcon(String key){ 53 | if (icons.containsKey(key)) return icons.get(key); 54 | String icon = iconConfig.getString(key); 55 | if (icon == null) icon = "?"; 56 | icons.put(key, icon); 57 | return icon; 58 | } 59 | 60 | private @NotNull String translateColor(@NotNull String colorDescription){ 61 | String pattern = colorDescription.replace('#', 'x').chars().mapToObj(c -> "&" + (char) c).collect(Collectors.joining()); 62 | return ChatColor.translateAlternateColorCodes('&', pattern); 63 | } // 64 | 65 | public ChatColor getColorByValue(Object value){ 66 | if (value == null) return getColor("types.null"); 67 | if (value instanceof Boolean) return getColor("types.bool"); 68 | if (value instanceof Character) return getColor("types.char"); 69 | if (value instanceof Byte) return getColor("types.byte"); 70 | if (value instanceof Short) return getColor("types.short"); 71 | if (value instanceof Integer) return getColor("types.int"); 72 | if (value instanceof Long) return getColor("types.long"); 73 | if (value instanceof Float) return getColor("types.float"); 74 | if (value instanceof Double) return getColor("types.double"); 75 | if (value instanceof String) return getColor("types.string"); 76 | if (value instanceof byte[]) return getColor("types.byte[]"); 77 | if (value instanceof int[]) return getColor("types.int[]"); 78 | if (value instanceof long[]) return getColor("types.long[]"); 79 | if (value instanceof Map) return getColor("types.map"); 80 | if (value instanceof Collection) return getColor("types.list"); 81 | return getColor("types.unknown"); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/command/action/ActionAddAll.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.command.action; 2 | 3 | import me.dpohvar.powernbt.PowerNBT; 4 | import me.dpohvar.powernbt.api.NBTCompound; 5 | import me.dpohvar.powernbt.api.NBTList; 6 | import me.dpohvar.powernbt.api.NBTManagerUtils; 7 | import me.dpohvar.powernbt.nbt.NBTContainer; 8 | import me.dpohvar.powernbt.nbt.NBTType; 9 | import me.dpohvar.powernbt.utils.Caller; 10 | import me.dpohvar.powernbt.utils.query.NBTQuery; 11 | 12 | import java.util.Arrays; 13 | import java.util.List; 14 | 15 | public class ActionAddAll extends Action { 16 | 17 | private final Caller caller; 18 | private final Argument arg1; 19 | private final Argument arg2; 20 | 21 | public ActionAddAll(Caller caller, String o1, String q1, String o2, String q2) { 22 | this.caller = caller; 23 | this.arg1 = new Argument(caller, o1, q1); 24 | this.arg2 = new Argument(caller, o2, q2); 25 | } 26 | 27 | @Override 28 | public void execute() throws Exception { 29 | if (arg1.needPrepare()) { 30 | arg1.prepare(this, null, null); 31 | return; 32 | } 33 | NBTContainer container1 = arg1.getContainer(); 34 | NBTQuery query1 = arg1.getQuery(); 35 | if (arg2.needPrepare()) { 36 | arg2.prepare(this, container1, query1); 37 | return; 38 | } 39 | Object base1 = container1.getCustomTag(query1); 40 | NBTContainer container2 = arg2.getContainer(); 41 | NBTQuery query2 = arg2.getQuery(); 42 | Object base2 = container2.getCustomTag(query2); 43 | if (base1 == null) { 44 | base1 = NBTType.fromValue(base2).getDefaultValue(); 45 | } 46 | if (base1 instanceof NBTCompound cmp1 && base2 instanceof NBTCompound cmp2){ 47 | cmp1.merge(cmp2); 48 | container1.setCustomTag(query1,cmp1); 49 | caller.sendValue(PowerNBT.plugin.translate("success_add"), cmp2, false, false); 50 | } else if (base1 instanceof NBTList list1 && base2 instanceof NBTList list2){ 51 | list1.addAll(list2); 52 | container1.setCustomTag(query1,list1); 53 | caller.sendValue(PowerNBT.plugin.translate("success_add"), list2,false, false); 54 | } else if (base1 instanceof String s1 && base2 instanceof String s2){ 55 | s1 += s2; 56 | container1.setCustomTag(query1,s1); 57 | caller.sendValue(PowerNBT.plugin.translate("success_add"), s2,false, false); 58 | } else if (base1 instanceof Number x1 && base2 instanceof Number x2){ 59 | NBTType x1Type = NBTType.fromValue(x1); 60 | if(x1 instanceof Float || x1 instanceof Double){ 61 | x1 = x1.doubleValue()+x2.doubleValue(); 62 | } else { 63 | x1 = x1.longValue()+x2.longValue(); 64 | } 65 | x1 = (Number) NBTManagerUtils.convertValue(x1, x1Type.type); 66 | container1.setCustomTag(query1, x1); 67 | caller.sendValue(PowerNBT.plugin.translate("success_add"), x2,false, false); 68 | } else if (base1.getClass().isArray() && base2.getClass().isArray()){ 69 | NBTType baseType = NBTType.fromValue(base1).getBaseType(); 70 | Object[] array1 = NBTManagerUtils.convertToObjectArrayOrNull(base1); 71 | Object[] array2 = NBTManagerUtils.convertToObjectArrayOrNull(base2); 72 | List list1 = Arrays.asList(array1); 73 | for (Object val : array2) { 74 | list1.add(NBTManagerUtils.convertValue(val, baseType.type)); 75 | } 76 | Object result = NBTManagerUtils.convertValue(list1, baseType.type); 77 | container1.setCustomTag(query1,result); 78 | caller.sendValue(PowerNBT.plugin.translate("success_add"), base2,false, false); 79 | } else { 80 | caller.send(PowerNBT.plugin.translate("fail_add")); 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/utils/viewer/components/NavbarElement.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.utils.viewer.components; 2 | 3 | import me.dpohvar.powernbt.utils.query.NBTQuery; 4 | import me.dpohvar.powernbt.utils.query.QSelector; 5 | import me.dpohvar.powernbt.utils.viewer.ContainerControl; 6 | import me.dpohvar.powernbt.utils.viewer.EventBuilder; 7 | import me.dpohvar.powernbt.utils.viewer.ViewerStyle; 8 | import net.md_5.bungee.api.ChatColor; 9 | import net.md_5.bungee.api.chat.BaseComponent; 10 | import net.md_5.bungee.api.chat.TextComponent; 11 | 12 | import java.util.List; 13 | 14 | public class NavbarElement implements Element { 15 | 16 | private final TextComponent component; 17 | 18 | public NavbarElement(ViewerStyle style, ContainerControl control){ 19 | 20 | NBTQuery query = control.getAccessQuery(); 21 | if (control.isReadonly()) { 22 | StringBuilder builder = new StringBuilder(); 23 | Object value = control.getValue(); 24 | builder.append(style.getColorByValue(value)); 25 | String valueType = value == null ? "null" : value.getClass().getSimpleName(); 26 | builder.append(valueType); 27 | 28 | if (query != null) { 29 | builder.append(" "); 30 | builder.append(style.getColor("disabledBreadcrumbs.query")); 31 | builder.append(query); 32 | } 33 | this.component = new TextComponent(builder.toString()); 34 | } else { 35 | TextComponent component = new TextComponent(""); 36 | String selector = control.getSelector(); 37 | InteractiveElement rootElement = new InteractiveElement( 38 | style.getColor("breadcrumbs.root"), 39 | control.getContainer().getRootContainer().toString(), 40 | EventBuilder.runNbt(selector, false), 41 | EventBuilder.popup("select " + control.getContainer().getRootContainer()), 42 | null 43 | ); 44 | component.addExtra(rootElement.getComponent()); 45 | component.addExtra(" "); 46 | 47 | QSelector lastStep = null; 48 | List steps = query.getSelectors(); 49 | ChatColor delimiterColor = style.getColor("breadcrumbs.delimiter"); 50 | for (int i = 0; i < steps.size(); i++) { 51 | QSelector step = steps.get(i); 52 | NBTQuery stepQuery = query.getSlice(0, i+1); 53 | 54 | String separator = step.getSeparator(lastStep); 55 | if (separator != null) component.addExtra(delimiterColor + separator); 56 | InteractiveElement interactiveElement = new InteractiveElement( 57 | style.getColorMod("breadcrumbs.steps", i), 58 | step.toString(), 59 | EventBuilder.runNbt(selector + " " + stepQuery, false), 60 | EventBuilder.popup("select " + step), 61 | null 62 | ); 63 | component.addExtra(interactiveElement.getComponent()); 64 | lastStep = step; 65 | } 66 | 67 | if (steps.size() > 0) component.addExtra(" "); 68 | String nextSelector = steps.size() == 0 ? selector + " " : control.getSelectorWithQuery()+"."; 69 | InteractiveElement nextSelectElement = new InteractiveElement( 70 | style.getColorMod("breadcrumbs.steps", steps.size()), 71 | "...", 72 | EventBuilder.suggestNbt(nextSelector, false), 73 | EventBuilder.popup("select next"), 74 | null 75 | ); 76 | component.addExtra(nextSelectElement.getComponent()); 77 | 78 | this.component = component; 79 | } 80 | } 81 | 82 | @Override 83 | public BaseComponent getComponent() { 84 | return component; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/nbt/NBTContainerComplex.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.nbt; 2 | 3 | import me.dpohvar.powernbt.exception.NBTQueryException; 4 | import me.dpohvar.powernbt.exception.NBTTagNotFound; 5 | import me.dpohvar.powernbt.utils.query.NBTQuery; 6 | 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | public class NBTContainerComplex extends NBTContainer { 11 | 12 | private final NBTContainer container; 13 | private final NBTQuery query; 14 | 15 | 16 | public NBTContainerComplex(NBTContainer container, NBTQuery query) { 17 | super(container.getSelector()); 18 | this.container = container; 19 | this.query = query; 20 | } 21 | 22 | public NBTContainerComplex(NBTContainer container, NBTQuery query, String name) { 23 | super(name); 24 | this.container = container; 25 | this.query = query; 26 | } 27 | 28 | @Override 29 | public NBTContainer getObject() { 30 | return this.container; 31 | } 32 | 33 | @Override 34 | public List getTypes() { 35 | return new ArrayList(); 36 | } 37 | 38 | public NBTQuery getQuery() { 39 | return this.query; 40 | } 41 | 42 | @Override 43 | public Object readTag() { 44 | try { 45 | return query.get(container.getTag()); 46 | } catch (NBTTagNotFound nbtTagNotFound) { 47 | return null; 48 | } 49 | } 50 | 51 | @Override 52 | public Object readCustomTag() { 53 | try { 54 | return query.get(container.getCustomTag()); 55 | } catch (NBTTagNotFound nbtTagNotFound) { 56 | throw new RuntimeException(nbtTagNotFound); 57 | } 58 | } 59 | 60 | @Override 61 | public void writeTag(Object base) { 62 | try { 63 | Object res = query.set(container.getTag(),base); 64 | container.writeTag(res); 65 | } catch (NBTQueryException exception) { 66 | throw new RuntimeException(exception.getMessage(),exception); 67 | } 68 | } 69 | 70 | @Override 71 | public void writeCustomTag(Object base) { 72 | try { 73 | Object res = query.set(container.getCustomTag(),base); 74 | container.setCustomTag(res); 75 | } catch (NBTQueryException exception) { 76 | throw new RuntimeException(exception.getMessage(),exception); 77 | } 78 | } 79 | 80 | @Override 81 | public void eraseTag() { 82 | try { 83 | Object res = query.remove(container.getTag()); 84 | container.setTag(res); 85 | } catch (NBTTagNotFound exception) { 86 | throw new RuntimeException(exception.getMessage(),exception); 87 | } 88 | } 89 | 90 | @Override 91 | public void eraseCustomTag() { 92 | try { 93 | Object res = query.remove(container.getCustomTag()); 94 | container.setCustomTag(res); 95 | } catch (NBTTagNotFound exception) { 96 | throw new RuntimeException(exception.getMessage(),exception); 97 | } 98 | } 99 | 100 | @Override 101 | protected Class getContainerClass() { 102 | return NBTContainer.class; 103 | } 104 | 105 | @Override 106 | public String toString(){ 107 | if (query==null || query.toString().isEmpty()) return "<"+container.toString()+">"; 108 | else return "<"+container.toString()+" "+query+">"; 109 | } 110 | 111 | @Override 112 | public NBTQuery getSelectorQuery() { 113 | if (this.getSelector() != null) return new NBTQuery(); 114 | NBTQuery selectorQuery = container.getSelectorQuery(); 115 | if (selectorQuery == null) return query; 116 | return selectorQuery.join(query); 117 | } 118 | 119 | @Override 120 | public NBTContainer getRootContainer(){ 121 | return container.getRootContainer(); 122 | } 123 | 124 | @Override 125 | public boolean isObjectReadonly(){ 126 | return container.isObjectReadonly(); 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/completer/TypeCompleter.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.completer; 2 | 3 | import me.dpohvar.powernbt.nbt.NBTType; 4 | import me.dpohvar.powernbt.utils.query.NBTQuery; 5 | import org.bukkit.Bukkit; 6 | import org.yaml.snakeyaml.Yaml; 7 | 8 | import java.io.File; 9 | import java.io.FileReader; 10 | import java.util.*; 11 | import java.util.logging.Level; 12 | 13 | public class TypeCompleter { 14 | 15 | private HashMap templates = new HashMap(); 16 | 17 | public TypeCompleter(File ymlFolder) { 18 | try { 19 | Yaml yaml = new Yaml(); 20 | File file = new File(ymlFolder, "templates.yml"); 21 | if (!file.exists()) return; 22 | FileReader reader = new FileReader(file); 23 | Object ymlRoot = yaml.load(reader); 24 | reader.close(); 25 | if (!(ymlRoot instanceof Map)) throw new RuntimeException("invalid yml format in file " + file); 26 | for (Map.Entry el : ((Map) ymlRoot).entrySet()) { 27 | String name = el.getKey(); 28 | String filename = el.getValue().toString(); 29 | file = new File(ymlFolder, filename); 30 | addToTemplates(name, file); 31 | } 32 | } catch (Exception e) { 33 | Bukkit.getLogger().log(Level.ALL, "can not autocomplete tml "+ymlFolder, e); 34 | } 35 | } 36 | 37 | private void addToTemplates(String name, File file) throws Exception { 38 | FileReader reader = new FileReader(file); 39 | Object ymlRoot = new Yaml().load(reader); 40 | reader.close(); 41 | templates.put(name, ymlRoot); 42 | } 43 | 44 | public List getNextKeys(String key, NBTQuery query) { 45 | List res = new ArrayList(); 46 | Object x = getObjectByQueue(key, query.getQueue()); 47 | if (x instanceof List) res.add("[]"); 48 | else if (x instanceof Map) { 49 | for (String s : ((Map) x).keySet()) { 50 | res.add(s); 51 | } 52 | } 53 | return res; 54 | } 55 | 56 | public NBTType getType(String key, NBTQuery query) { 57 | Object x = getObjectByQueue(key, query.getQueue()); 58 | if (x instanceof String) { 59 | return NBTType.fromString((String) x); 60 | } 61 | return null; 62 | } 63 | 64 | private Object getObjectByQueue(String key, Queue queue) { 65 | Object current = templates.get(key); 66 | if (key != null) while (true) { 67 | Object t = queue.poll(); 68 | if (current == null) return null; 69 | if (current instanceof Map && t instanceof String) { 70 | current = ((Map) current).get(t); 71 | continue; 72 | } 73 | if (current instanceof List && t instanceof Integer) { 74 | current = ((List) current).get(0); 75 | continue; 76 | } 77 | if (current instanceof String) { 78 | String s = (String) current; 79 | if (s.endsWith("[]")) { 80 | if (t == null) return s; 81 | if (queue.isEmpty()) return s.substring(0, s.length() - 2); 82 | return null; 83 | } 84 | if (templates.containsKey(current)) { 85 | LinkedList l = new LinkedList(queue); 86 | l.addFirst(t); 87 | return getObjectByQueue((String) current, l); 88 | } 89 | return queue.isEmpty() ? current : null; 90 | } 91 | return current; 92 | } 93 | else { 94 | Object r = null; 95 | for (String subKey : templates.keySet()) { 96 | r = getObjectByQueue(subKey, new LinkedList(queue)); 97 | if (r != null) break; 98 | } 99 | return r; 100 | } 101 | } 102 | 103 | } 104 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/completer/Completer.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.completer; 2 | 3 | import me.dpohvar.powernbt.utils.Caller; 4 | import me.dpohvar.powernbt.utils.StringParser; 5 | import org.apache.commons.lang.StringUtils; 6 | import org.bukkit.command.Command; 7 | import org.bukkit.command.CommandSender; 8 | import org.bukkit.command.TabCompleter; 9 | 10 | import java.util.ArrayList; 11 | import java.util.LinkedHashSet; 12 | import java.util.LinkedList; 13 | import java.util.List; 14 | 15 | import static me.dpohvar.powernbt.PowerNBT.plugin; 16 | 17 | public abstract class Completer implements TabCompleter { 18 | public class TabFormer { 19 | private final String query; 20 | private final LinkedHashSet tabs = new LinkedHashSet(); 21 | LinkedList words = new LinkedList(); 22 | 23 | public boolean isQueryEmpty() { 24 | return query == null || query.isEmpty(); 25 | } 26 | 27 | public String getQuery() { 28 | return query; 29 | } 30 | 31 | public String pollAllAsString() { 32 | String s = StringUtils.join(words, ' '); 33 | words.clear(); 34 | return s; 35 | } 36 | 37 | public boolean isLastQuery() { 38 | return words.isEmpty() && (query == null || query.isEmpty()); 39 | } 40 | 41 | public TabFormer(List val) { 42 | words = new LinkedList<>(val); 43 | if (words.size() == 0) query = ""; 44 | else query = words.pollLast(); 45 | } 46 | 47 | public String poll() { 48 | String s = words.poll(); 49 | return s == null ? "" : s; 50 | } 51 | 52 | public int size() { 53 | return words.size(); 54 | } 55 | 56 | public void add(String... strings) { 57 | for (String s : strings) if (s != null) tabs.add(s); 58 | } 59 | 60 | public void addIfStarts(String... strings) { 61 | for (String s : strings) if (s.toLowerCase().startsWith(query.toLowerCase())) tabs.add(s); 62 | } 63 | 64 | public void addIfStartsCase(String... strings) { 65 | for (String s : strings) if (s.startsWith(query)) tabs.add(s); 66 | } 67 | 68 | public void addIfHas(String... strings) { 69 | for (String s : strings) if (s.toLowerCase().contains(query.toLowerCase())) tabs.add(s); 70 | } 71 | 72 | public void addIfHasCase(String... strings) { 73 | for (String s : strings) if (s.contains(query)) tabs.add(s); 74 | } 75 | 76 | public List getResult() { 77 | return new ArrayList(tabs); 78 | } 79 | } 80 | 81 | @Override 82 | public List onTabComplete(CommandSender sender, Command command, String alias, String[] args) { 83 | Caller caller = plugin.getCaller(sender); 84 | TabFormer former = null; 85 | String line = StringUtils.join(args, ' '); 86 | try { 87 | LinkedList words = new LinkedList(); 88 | for (String s : plugin.getTokenizer().tokenize(line).values()) { 89 | if (s.startsWith("\"") && s.endsWith("\"")) { 90 | s = "\""+StringParser.parse(s.substring(1, s.length() - 1))+"\""; 91 | } 92 | words.add(s); 93 | } 94 | if (line.endsWith(" ")) words.add(""); 95 | former = new TabFormer(words); 96 | fillTabs(caller, former); 97 | return former.getResult(); 98 | } catch (Throwable t) { 99 | if (former == null) return new ArrayList(); 100 | return former.getResult(); 101 | } 102 | } 103 | 104 | protected abstract void fillTabs(Caller caller, TabFormer former) throws Exception; 105 | 106 | protected static boolean isEmpty(String s) { 107 | return s == null || s.isEmpty(); 108 | } 109 | 110 | protected static boolean matches(String command, String... t) { 111 | if (command == null) return false; 112 | for (String s : t) if (command.equals(s)) return true; 113 | return false; 114 | } 115 | 116 | } 117 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/utils/viewer/components/MapElement.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.utils.viewer.components; 2 | 3 | import me.dpohvar.powernbt.utils.query.KeySelector; 4 | import me.dpohvar.powernbt.utils.viewer.ContainerControl; 5 | import me.dpohvar.powernbt.utils.viewer.DisplayValueHelper; 6 | import me.dpohvar.powernbt.utils.viewer.EventBuilder; 7 | import me.dpohvar.powernbt.utils.viewer.ViewerStyle; 8 | import net.md_5.bungee.api.ChatColor; 9 | import net.md_5.bungee.api.chat.BaseComponent; 10 | import net.md_5.bungee.api.chat.TextComponent; 11 | 12 | import java.util.ArrayList; 13 | import java.util.Map; 14 | 15 | public class MapElement implements Element { 16 | 17 | private final TextComponent component; 18 | 19 | public MapElement(ViewerStyle style, ContainerControl control, Map map, int start, int end, int limitCol, int limitRow, boolean hex, boolean bin){ 20 | this.component = getValuesComponent(style, control, map, start, end, limitCol, limitRow, hex, bin); 21 | } 22 | 23 | private static TextComponent getValuesComponent(ViewerStyle style, ContainerControl control, Map map, int start, int end, int limitCol, int limitRow, boolean hex, boolean bin){ 24 | int toEnd = end; 25 | if (start == 0 && toEnd == 0) toEnd = limitCol; 26 | ArrayList> entries = new ArrayList<>(map.entrySet()); 27 | if (entries.size() == 0) { 28 | return new TextComponent("empty"); 29 | } 30 | TextComponent component = new TextComponent(""); 31 | 32 | boolean readonly = control.isReadonly(); 33 | for (int i = start; i < Math.min(toEnd, map.size()); i++) { 34 | Map.Entry entry = entries.get(i); 35 | Object mapValue = entry.getValue(); 36 | Object key = entry.getKey(); 37 | if (key instanceof String mapKey) { 38 | KeySelector selector = new KeySelector(mapKey); 39 | if (readonly) { 40 | StringBuilder builder = new StringBuilder(); 41 | if (i != start) builder.append("\n").append(ChatColor.RESET); 42 | builder.append(style.getColorByValue(mapValue)).append(selector).append(ChatColor.RESET).append(": "); 43 | component.addExtra(builder.toString()); 44 | } else { 45 | String mapValueType = mapValue == null ? "null" : mapValue.getClass().getSimpleName(); 46 | InteractiveElement keyNameElement = new InteractiveElement( 47 | style.getColorByValue(mapValue), 48 | selector.toString(), 49 | EventBuilder.runNbt(control.getSelector() + " " + control.getAccessQuery().add(selector), false), 50 | EventBuilder.popup("type "+ mapValueType+ "\nselect " + mapKey), 51 | null 52 | ); 53 | if (i != start) component.addExtra("\n"); 54 | component.addExtra(keyNameElement.getComponent()); 55 | component.addExtra(": "); 56 | } 57 | 58 | } else { 59 | StringBuilder builder = new StringBuilder(); 60 | if (i != start) builder.append("\n"); 61 | builder.append(style.getColorByValue(mapValue)).append("").append(ChatColor.RESET).append(": "); 62 | component.addExtra(builder.toString()); 63 | } 64 | // VALUE 65 | String shortValue = DisplayValueHelper.getShortValue(style, mapValue, limitRow, hex, bin); 66 | if (ChatColor.stripColor(shortValue).isEmpty()) shortValue+=" "; 67 | if (readonly || (!(key instanceof String mapKey))) { 68 | component.addExtra(shortValue); 69 | } else { 70 | KeySelector selector = new KeySelector(mapKey); 71 | InteractiveElement ValueElement = new InteractiveElement( 72 | null, 73 | shortValue, 74 | EventBuilder.suggestNbt(control.getSelector() + " " + control.getAccessQuery().add(selector) + " = ", false), 75 | EventBuilder.popup("edit"), 76 | null 77 | ); 78 | component.addExtra(ValueElement.getComponent()); 79 | } 80 | } 81 | return component; 82 | 83 | } 84 | 85 | @Override 86 | public BaseComponent getComponent() { 87 | return component; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/utils/viewer/DisplayValueHelper.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.utils.viewer; 2 | 3 | import me.dpohvar.powernbt.api.NBTManagerUtils; 4 | import net.md_5.bungee.api.ChatColor; 5 | import org.apache.commons.lang.StringUtils; 6 | 7 | import java.nio.charset.StandardCharsets; 8 | import java.util.ArrayList; 9 | import java.util.Map; 10 | 11 | public class DisplayValueHelper { 12 | 13 | public static String getShortValue(ViewerStyle style, Object base, int rowLimit, boolean hex, boolean bin){ 14 | String value = getShortValueFull(style, base, hex, bin); 15 | int overText = Math.max(org.bukkit.ChatColor.stripColor(value).length()-rowLimit,value.length()-rowLimit*2); 16 | String resetPattern = org.bukkit.ChatColor.RESET.toString(); 17 | if ( value.endsWith(resetPattern) ) { 18 | value = value.substring(0,value.length()-resetPattern.length()); 19 | } 20 | if (overText>0){ 21 | value=value.substring(0,rowLimit-1).concat(style.getColor("etc")+"\u2026"); 22 | } 23 | return value; 24 | } 25 | 26 | public static String getStringValue(ViewerStyle style, String textValue, int start, int end, int limit, boolean hex){ 27 | boolean postfix = false;// 28 | int toEnd = end; 29 | if (start == 0 && end == 0) { 30 | toEnd = limit; 31 | postfix = true; 32 | } 33 | if (start > textValue.length()) { 34 | return ""; 35 | } 36 | 37 | if (toEnd >= textValue.length()) { 38 | toEnd = textValue.length(); 39 | postfix = false; 40 | } 41 | textValue = textValue.substring(start, toEnd); 42 | 43 | if (hex) { 44 | ArrayList h = new ArrayList<>(); 45 | for (byte b : textValue.getBytes(StandardCharsets.UTF_8)) h.add(Integer.toHexString(b & 0xFF)); 46 | textValue = StringUtils.join(h, ' '); 47 | } 48 | if (postfix) textValue += '\u2026'; 49 | 50 | return textValue; 51 | } 52 | 53 | private static String getShortValueFull(ViewerStyle style, Object base, boolean hex, boolean bin){ 54 | 55 | if (base == null) return "null"; 56 | if (base instanceof Boolean) return base.toString(); 57 | if (base instanceof Character) return base.toString(); 58 | if (base instanceof Number number) { 59 | if (hex) return toHex(number); 60 | if (bin) return toBinary(number); 61 | return number.toString(); 62 | } 63 | if (base instanceof String value) { 64 | if (hex) { 65 | ArrayList h = new ArrayList<>(); 66 | for (byte b : value.getBytes(StandardCharsets.UTF_8)) h.add(Integer.toHexString(b & 0xFF)); 67 | return StringUtils.join(h, ' '); 68 | } 69 | return value; 70 | } 71 | if (base instanceof Map tag) { 72 | if (tag.size() == 0) { 73 | return "empty"; 74 | } else { 75 | ArrayList h = new ArrayList<>(); 76 | for (Map.Entry b : tag.entrySet()) { 77 | Object key = b.getKey(); 78 | if (!(key instanceof String stringKey)) continue; 79 | ChatColor color = style.getColorByValue(b.getValue()); 80 | h.add(color + stringKey + ChatColor.RESET); 81 | } 82 | return "{" + tag.size() + "}: " + StringUtils.join(h, ","); 83 | } 84 | } 85 | Object[] array = NBTManagerUtils.convertToObjectArrayOrNull(base); 86 | if (array != null) { 87 | if (array.length == 0) return "[0] empty"; 88 | return "["+array.length+"]"; 89 | } 90 | return "unknown value"; 91 | } 92 | 93 | private static String toHex(Number value){ 94 | if (value instanceof Byte number) return "#"+Integer.toHexString(number & 0xFF); 95 | if (value instanceof Short number) return "#"+Integer.toHexString(number & 0xFFFF); 96 | if (value instanceof Integer number) return "#"+Long.toHexString(number.longValue() & 0xFFFFFFFFL); 97 | if (value instanceof Long number) return "#"+Long.toHexString(number); 98 | if (value instanceof Float number) return "#"+Float.toHexString(number); 99 | if (value instanceof Double number) return "#"+Double.toHexString(number); 100 | return String.valueOf(value); 101 | } 102 | 103 | private static String toBinary(Number value){ 104 | if (value instanceof Byte number) return "#"+Integer.toBinaryString(number & 0xFF); 105 | if (value instanceof Short number) return "#"+Integer.toBinaryString(number & 0xFFFF); 106 | if (value instanceof Integer number) return "#"+Long.toBinaryString(number.longValue() & 0xFFFFFFFFL); 107 | if (value instanceof Long number) return "#"+Long.toBinaryString(number); 108 | return String.valueOf(value); 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/utils/Caller.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.utils; 2 | 3 | import me.dpohvar.powernbt.command.action.Action; 4 | import me.dpohvar.powernbt.command.action.Argument; 5 | import me.dpohvar.powernbt.nbt.NBTContainer; 6 | import me.dpohvar.powernbt.utils.query.NBTQuery; 7 | import me.dpohvar.powernbt.utils.viewer.InteractiveViewer; 8 | import net.md_5.bungee.api.chat.TextComponent; 9 | import org.bukkit.Bukkit; 10 | import org.bukkit.ChatColor; 11 | import org.bukkit.command.CommandSender; 12 | import org.bukkit.entity.Player; 13 | 14 | import java.util.Arrays; 15 | import java.util.HashMap; 16 | import java.util.List; 17 | import java.util.logging.Level; 18 | 19 | import static me.dpohvar.powernbt.PowerNBT.plugin; 20 | 21 | public class Caller extends NBTContainer { 22 | private CommandSender owner; 23 | private boolean silent; 24 | private Object base; 25 | private Argument argument; 26 | private Action action; 27 | private final HashMap> variables = new HashMap<>(); 28 | 29 | public Argument getArgument() { 30 | return argument; 31 | } 32 | 33 | public Action getAction() { 34 | return action; 35 | } 36 | 37 | public void hold(Argument argument, Action action) { 38 | this.argument = argument; 39 | this.action = action; 40 | } 41 | 42 | public boolean isSilent() { 43 | return silent; 44 | } 45 | 46 | public void setSilent(boolean silent) { 47 | this.silent = silent; 48 | } 49 | 50 | public CommandSender getOwner() { 51 | return owner; 52 | } 53 | 54 | public void setOwner(CommandSender owner) { 55 | this.owner = owner; 56 | } 57 | 58 | public HashMap> getVariables() { 59 | return variables; 60 | } 61 | 62 | public NBTContainer getVariable(String name) { 63 | return variables.get(name); 64 | } 65 | 66 | public void setVariable(String name, NBTContainer value) { 67 | variables.put(name, value); 68 | } 69 | 70 | public void removeVariable(String name) { 71 | variables.remove(name); 72 | } 73 | 74 | private boolean isInteractiveMode(Player player){ 75 | return plugin.getConfig().getBoolean("editor.enabled"); 76 | } 77 | 78 | public void send(Object o) { 79 | if (silent) return; 80 | String message = plugin.getPrefix() + o; 81 | if (message.length()>32743) message = message.substring(0,32743); 82 | owner.sendMessage(message); 83 | } 84 | 85 | public void sendValue(String prefix, Object value, boolean hex, boolean bin) { 86 | String message = plugin.getPrefix() + prefix + " " + NBTStaticViewer.getShortValueWithPrefix(value, hex, bin); 87 | if (message.length()>32743) message = message.substring(0,32743); 88 | owner.sendMessage(message); 89 | owner.sendMessage(); 90 | } 91 | 92 | public void sendValueView(String prefix, NBTContainer container, NBTQuery query, int start, int end, boolean hex, boolean bin) throws Exception { 93 | Object value = container.getCustomTag(query); 94 | String message = plugin.getPrefix() + prefix + " " + NBTStaticViewer.getFullValue(value, start, end, hex, bin); 95 | if (message.length()>32743) message = message.substring(0,32743); 96 | owner.sendMessage(message); 97 | owner.sendMessage(); 98 | } 99 | 100 | public void handleException(Throwable o) { 101 | String message; 102 | if (o.getClass().equals(RuntimeException.class)) { 103 | message = plugin.getErrorPrefix() + o.getMessage(); 104 | 105 | } else { 106 | message = plugin.getErrorPrefix() + 107 | ChatColor.RED + ChatColor.BOLD + 108 | o.getClass().getSimpleName() + ": " + ChatColor.RESET+ o.getMessage(); 109 | } 110 | if (message.length()>32743) message = message.substring(0,32743); 111 | owner.sendMessage(message); 112 | if (plugin.isDebug()) { 113 | Bukkit.getLogger().log(Level.ALL, message, o); 114 | } 115 | } 116 | 117 | public Caller(CommandSender owner) { 118 | super("buffer"); 119 | this.owner = owner; 120 | } 121 | 122 | @Override 123 | public List getTypes() { 124 | return Arrays.asList("entity", "living", "entity_Player"); 125 | } 126 | 127 | @Override 128 | public Caller getObject() { 129 | return this; 130 | } 131 | 132 | @Override 133 | public Object readTag() { 134 | return this.base; 135 | } 136 | 137 | @Override 138 | public void writeTag(Object base) { 139 | this.base = base; 140 | } 141 | 142 | @Override 143 | public Class getContainerClass() { 144 | return Caller.class; 145 | } 146 | 147 | @Override 148 | public void eraseTag() { 149 | this.base = null; 150 | } 151 | 152 | @Override 153 | public String getSelector() { 154 | return "buffer"; 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/utils/query/IntegerSelector.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.utils.query; 2 | 3 | import me.dpohvar.powernbt.api.NBTList; 4 | import me.dpohvar.powernbt.api.NBTManagerUtils; 5 | import me.dpohvar.powernbt.exception.NBTTagNotFound; 6 | import me.dpohvar.powernbt.nbt.NBTType; 7 | import org.apache.commons.lang.StringUtils; 8 | 9 | import java.util.ArrayList; 10 | import java.util.Collection; 11 | import java.util.List; 12 | 13 | public interface IntegerSelector extends QSelector { 14 | 15 | @Override 16 | default Object get(Object current, boolean useDefault) throws NBTTagNotFound { 17 | if (useDefault && current == null) return null; 18 | if (current instanceof List list) { 19 | int index = indexToGet(list.size()); 20 | if (index >= list.size()) { 21 | if (useDefault) return null; 22 | throw new NBTTagNotFound(current, this.toString()); 23 | } 24 | return list.get(index); 25 | } 26 | if (current instanceof Collection col) { 27 | int index = indexToGet(col.size()); 28 | if (index >= col.size()) { 29 | if (useDefault) return null; 30 | throw new NBTTagNotFound(current, this.toString()); 31 | } 32 | return col.toArray()[index]; 33 | } 34 | if (current instanceof String s) { 35 | int index = indexToGet(s.length()); 36 | if (index >= s.length()) { 37 | if (useDefault) return ""; 38 | throw new NBTTagNotFound(current, this.toString()); 39 | } 40 | return s.substring(index, index+1); 41 | } 42 | Object[] objects = NBTManagerUtils.convertToObjectArrayOrNull(current); 43 | if (objects != null) { 44 | int index = indexToGet(objects.length); 45 | if (index >= objects.length) { 46 | if (useDefault) return ""; 47 | throw new NBTTagNotFound(current, this.toString()); 48 | } 49 | return objects[index]; 50 | } 51 | throw new NBTTagNotFound(current, this.toString()); 52 | } 53 | 54 | int indexToGet(int size); 55 | int indexToSet(int size); 56 | int indexToDelete(int size); 57 | 58 | @Override 59 | default Object delete(Object current) throws NBTTagNotFound { 60 | if (current instanceof Collection col) { 61 | List list = cloneCollection(col); 62 | list.remove(indexToDelete(list.size())); 63 | return list; 64 | } 65 | if (current instanceof String s) { 66 | int index = indexToDelete(s.length()); 67 | return s.substring(0, index) + s.substring(index+1); 68 | } 69 | Object[] array = NBTManagerUtils.convertToObjectArrayOrNull(current); 70 | if (array != null) { 71 | return NBTManagerUtils.modifyArray(array, list -> list.remove(indexToDelete(array.length))); 72 | } 73 | throw new NBTTagNotFound(current, this.toString()); 74 | } 75 | 76 | @Override 77 | default Object set(Object current, Object value, boolean createDir) throws NBTTagNotFound { 78 | if (current == null && createDir) current = new ArrayList<>(); 79 | if (current instanceof Collection col) { 80 | List resultList = cloneCollection(col); 81 | putToFreeIndex(resultList, indexToSet(col.size()), value); 82 | return resultList; 83 | } 84 | if (current instanceof String s) { 85 | int length = s.length(); 86 | int index = indexToSet(length); 87 | String pasteValue = (String) NBTManagerUtils.convertValue(value, NBTType.STRING.type); 88 | if (index < length) { 89 | return s.substring(0, index) + pasteValue + s.substring(index+1); 90 | } 91 | return s + StringUtils.repeat(" ",length - index) + pasteValue; 92 | } 93 | Object array = NBTManagerUtils.modifyArray(current, list -> putToFreeIndex(list, indexToSet(list.size()), value)); 94 | if (array != null) return array; 95 | throw new NBTTagNotFound(current, this.toString()); 96 | } 97 | 98 | private static void putToFreeIndex(List list, int index, Object value) { 99 | int selectIndex = index; 100 | if (selectIndex < 0) selectIndex = list.size() - selectIndex; 101 | if (selectIndex < 0) throw new IndexOutOfBoundsException(selectIndex); 102 | if (selectIndex < list.size()) { 103 | list.set(selectIndex, value); 104 | return; 105 | } 106 | int addDefaultCount = selectIndex - list.size(); 107 | if (addDefaultCount > 0) { 108 | Object defaultValue = null; 109 | if (list instanceof NBTList nbtList) { 110 | NBTType nbtType = NBTType.fromByte(nbtList.getType()); 111 | if (nbtType != null) defaultValue = nbtType.getDefaultValue(); 112 | } 113 | while (addDefaultCount --> 0) list.add(defaultValue); 114 | } 115 | list.add(value); 116 | } 117 | 118 | public static List cloneCollection(Collection col){ 119 | if (col instanceof NBTList c) return c.clone(); 120 | return new ArrayList<>(col); 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /src/test/java/me/dpohvar/powernbt/BasicTest.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt; 2 | 3 | import me.dpohvar.powernbt.exception.NBTTagNotFound; 4 | import me.dpohvar.powernbt.exception.NBTTagUnexpectedType; 5 | import me.dpohvar.powernbt.nbt.NBTContainerValue; 6 | import me.dpohvar.powernbt.utils.query.NBTQuery; 7 | import org.junit.Assert; 8 | import org.junit.Test; 9 | 10 | import java.util.LinkedHashMap; 11 | import java.util.Map; 12 | 13 | public class BasicTest extends Assert { 14 | 15 | private static Object qGet(Object base, String selector) throws NBTTagNotFound { 16 | return new NBTContainerValue(base).getCustomTag(NBTQuery.fromString(selector)); 17 | } 18 | 19 | private static Object qSet(Object base, String selector, Object value) throws NBTTagNotFound, NBTTagUnexpectedType { 20 | NBTContainerValue container = new NBTContainerValue(base); 21 | container.setCustomTag(NBTQuery.fromString(selector), value); 22 | return container.getObject(); 23 | } 24 | 25 | private static Object qRemove(Object base, String selector) throws NBTTagNotFound { 26 | NBTContainerValue container = new NBTContainerValue(base); 27 | container.removeCustomTag(NBTQuery.fromString(selector)); 28 | return container.getObject(); 29 | } 30 | 31 | @Test 32 | public void testContainer(){ 33 | LinkedHashMap value = new LinkedHashMap<>(); 34 | NBTContainerValue container = new NBTContainerValue(value); 35 | assertEquals(value, container.getObject()); 36 | } 37 | 38 | @Test 39 | public void testGetJsonValue() throws NBTTagNotFound { 40 | NBTContainerValue container = new NBTContainerValue("{\"a\":12}"); 41 | NBTQuery query = NBTQuery.fromString("#a"); 42 | assertEquals((double) 12.0, container.getCustomTag(query)); 43 | } 44 | 45 | @Test 46 | public void testSetJsonValue() throws NBTTagNotFound, NBTTagUnexpectedType { 47 | NBTContainerValue container = new NBTContainerValue("{\"a\":12}"); 48 | NBTQuery query = NBTQuery.fromString("#a"); 49 | container.setCustomTag(query, 34.0); 50 | assertEquals((double) 34.0, container.getCustomTag(query)); 51 | } 52 | 53 | @Test 54 | public void testRemoveJsonValue() throws NBTTagNotFound { 55 | NBTContainerValue container = new NBTContainerValue("{\"a\":12}"); 56 | NBTQuery query = NBTQuery.fromString("#a"); 57 | container.removeCustomTag(query); 58 | assertEquals("{}", container.getObject()); 59 | } 60 | 61 | @Test 62 | public void testRemoveJsonString() throws NBTTagNotFound { 63 | NBTContainerValue container = new NBTContainerValue("{\"a\":12}"); 64 | NBTQuery query = NBTQuery.fromString("#"); 65 | container.removeCustomTag(query); 66 | assertEquals("", container.getObject()); 67 | } 68 | 69 | @Test 70 | public void testRemoveJsonValueString() throws NBTTagNotFound { 71 | LinkedHashMap value = new LinkedHashMap<>(); 72 | value.put("e", "{\"a\":12}"); 73 | NBTContainerValue container = new NBTContainerValue(value); 74 | NBTQuery query = NBTQuery.fromString("e#a"); 75 | container.removeCustomTag(query); 76 | Object modifiedObject = container.getObject(); 77 | assertTrue(modifiedObject instanceof Map); 78 | assertEquals("{}", ((Map)modifiedObject).get("e")); 79 | } 80 | 81 | @Test 82 | public void testByteArrayInsert() throws NBTTagNotFound, NBTTagUnexpectedType { 83 | NBTContainerValue container = new NBTContainerValue(new byte[]{1,2,3,4,5}); 84 | NBTQuery query = NBTQuery.fromString("[3..1]"); 85 | container.setCustomTag(query, new int[]{256+10, 256+20, 256+30}); 86 | assertArrayEquals(new byte[]{1,30,20,10,4,5}, (byte[]) container.getObject()); 87 | } 88 | 89 | @Test 90 | public void testByteArrayRemove() throws NBTTagNotFound { 91 | NBTContainerValue container = new NBTContainerValue(new byte[]{1,2,3,4,5}); 92 | NBTQuery query = NBTQuery.fromString("[3..1]"); 93 | container.removeCustomTag(query); 94 | assertArrayEquals(new byte[]{1,4,5}, (byte[]) container.getObject()); 95 | } 96 | 97 | @Test 98 | public void testByteArrayAddToEnd() throws NBTTagNotFound, NBTTagUnexpectedType { 99 | NBTContainerValue container = new NBTContainerValue(new byte[]{1,2,3,4,5}); 100 | NBTQuery query = NBTQuery.fromString("[..]"); 101 | container.setCustomTag(query, new int[]{6, 7, 8}); 102 | assertArrayEquals(new byte[]{1, 2, 3, 4, 5, 6, 7, 8}, (byte[]) container.getObject()); 103 | } 104 | 105 | @Test 106 | public void testByteArrayAddToStart() throws NBTTagNotFound, NBTTagUnexpectedType { 107 | NBTContainerValue container = new NBTContainerValue(new byte[]{1,2,3,4,5}); 108 | NBTQuery query = NBTQuery.fromString("[0..0]"); 109 | container.setCustomTag(query, new int[]{6, 7, 8}); 110 | assertArrayEquals(new byte[]{6, 7, 8, 1, 2, 3, 4, 5}, (byte[]) container.getObject()); 111 | } 112 | 113 | 114 | @Test 115 | public void testComplexSetterToNull() throws NBTTagNotFound, NBTTagUnexpectedType { 116 | Object value = qSet(null, "x[0].foo.bar#baz#[4]fiz", 12); 117 | Object selected = qGet(value, "x[0].foo.bar#baz#[4]fiz"); 118 | assertEquals(12.0, selected); 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/utils/query/RangeSelector.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.utils.query; 2 | 3 | import me.dpohvar.powernbt.api.NBTManagerUtils; 4 | import me.dpohvar.powernbt.exception.NBTTagNotFound; 5 | import me.dpohvar.powernbt.nbt.NBTType; 6 | import org.apache.commons.lang.ArrayUtils; 7 | 8 | import java.util.Arrays; 9 | import java.util.Collection; 10 | import java.util.Collections; 11 | import java.util.List; 12 | 13 | public record RangeSelector(Integer start, Integer end) implements QSelector { 14 | 15 | @Override 16 | public Object get(Object current, boolean useDefault) throws NBTTagNotFound { 17 | if (useDefault && current == null) return null; 18 | if (current instanceof String string) { 19 | int a = fixedIndex(start, string.length()); 20 | int b = fixedIndex(end, string.length()); 21 | boolean reverse = false; 22 | if (a == b) return ""; 23 | if (a > b) { 24 | reverse = true; 25 | int c = a; a = b; b = c; 26 | } 27 | String result = string.substring(a, b); 28 | if (!reverse) return result; 29 | return new StringBuilder(result).reverse().toString(); 30 | } 31 | if (current instanceof Collection col) { 32 | List list = IntegerSelector.cloneCollection(col); 33 | return getSubList(list); 34 | } 35 | Object arrayResult = NBTManagerUtils.mapArray(current, this::getSubList); 36 | if (arrayResult != null) return arrayResult; 37 | throw new NBTTagNotFound(current, this.toString()); 38 | } 39 | 40 | private List getSubList(List list){ 41 | int a = fixedIndex(start, list.size()); 42 | int b = fixedIndex(end, list.size()); 43 | boolean reverse = false; 44 | if (a > b) { 45 | reverse = true; 46 | int c = a; a = b; b = c; 47 | } 48 | List result = list.subList(a, b); 49 | if (reverse) Collections.reverse(result); 50 | return result; 51 | } 52 | 53 | private boolean clearRange(List col){ 54 | int a = fixedIndex(start, col.size()); 55 | int b = fixedIndex(end, col.size()); 56 | if (a == b) return false; 57 | if (a > b) {int c = a; a = b; b = c;} 58 | col.subList(a, b).clear(); 59 | return true; 60 | } 61 | 62 | public int fixedIndex(Integer index, int size){ 63 | if (index == null) return size; 64 | return index < 0 ? size + index : index; 65 | } 66 | 67 | @Override 68 | public Object delete(Object current) throws NBTTagNotFound { 69 | if (current instanceof String string) { 70 | int a = fixedIndex(start, string.length()); 71 | int b = fixedIndex(end, string.length()); 72 | if (a == b) return string; 73 | if (a > b) { int c = a; a = b; b = c; } 74 | return string.substring(0, a) + string.substring(b); 75 | } 76 | if (current instanceof Collection col){ 77 | List list = IntegerSelector.cloneCollection(col); 78 | boolean removed = this.clearRange(list); 79 | if (removed) return list; 80 | return current; 81 | } 82 | Object arrayResult = NBTManagerUtils.modifyArray(current, this::clearRange); 83 | if (arrayResult != null) return arrayResult; 84 | throw new NBTTagNotFound(current, this.toString()); 85 | } 86 | 87 | private void insertSubList(List list, Object valueToInsert){ 88 | int a = fixedIndex(start, list.size()); 89 | int b = fixedIndex(end, list.size()); 90 | boolean reverse = false; 91 | if (a > b) { 92 | reverse = true; 93 | int c = a; a = b; b = c; 94 | } 95 | Object[] objectsToInsert = NBTManagerUtils.convertToObjectArrayOrNull(valueToInsert); 96 | if (objectsToInsert == null) objectsToInsert = new Object[]{valueToInsert}; 97 | if (reverse) ArrayUtils.reverse(objectsToInsert); 98 | List result = list.subList(a, b); 99 | result.clear(); 100 | result.addAll(Arrays.asList(objectsToInsert)); 101 | } 102 | 103 | @Override 104 | public Object set(Object current, Object value, boolean createDir) throws NBTTagNotFound { 105 | if (current instanceof String s) { 106 | int a = fixedIndex(start, s.length()); 107 | int b = fixedIndex(end, s.length()); 108 | boolean reverse = false; 109 | if (a > b) { 110 | reverse = true; 111 | int c = a; a = b; b = c; 112 | } 113 | String before = s.substring(0, a); 114 | String after = s.substring(b); 115 | String pasteValue = (String) NBTManagerUtils.convertValue(value, NBTType.STRING.type); 116 | if (reverse) pasteValue = new StringBuilder(pasteValue).reverse().toString(); 117 | return before + pasteValue + after; 118 | } 119 | if (current instanceof Collection col){ 120 | List list = IntegerSelector.cloneCollection(col); 121 | insertSubList(list, value); 122 | return list; 123 | } 124 | Object arrayResult = NBTManagerUtils.modifyArray(current, list -> insertSubList(list, value)); 125 | if (arrayResult != null) return arrayResult; 126 | throw new NBTTagNotFound(current, this.toString()); 127 | } 128 | 129 | 130 | @Override 131 | public String toString() { 132 | String a = start == null ? "" : start.toString(); 133 | String b = end == null ? "" : end.toString(); 134 | return "["+a+".."+b+"]"; 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/utils/StringParser.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.utils; 2 | 3 | import me.dpohvar.powernbt.exception.ParseException; 4 | import org.bukkit.ChatColor; 5 | 6 | import static me.dpohvar.powernbt.utils.StringParser.Mode.*; 7 | 8 | /** 9 | * Created with IntelliJ IDEA. 10 | * User: DPOH-VAR 11 | * Date: 25.07.13 12 | * Time: 1:35 13 | */ 14 | public class StringParser { 15 | public enum Mode { 16 | CHAR, ESCAPE, UNICODE, SPACE 17 | } 18 | 19 | public static String parse(String input) throws ParseException { 20 | char[] chars = input.toCharArray(); 21 | StringBuilder buffer = new StringBuilder(); 22 | StringBuilder unicode = new StringBuilder(); 23 | Mode mode = Mode.CHAR; 24 | int row = 0; 25 | int col = -1; 26 | parse: 27 | for (char c : chars) { 28 | if (c == '\n') { 29 | col = 0; 30 | row++; 31 | } else { 32 | col++; 33 | } 34 | switch (mode) { 35 | case CHAR -> { 36 | switch (c) { 37 | case '\\' -> mode = ESCAPE; 38 | case '&' -> buffer.append(ChatColor.COLOR_CHAR); 39 | case '\"' -> throw new ParseException(input, row, col, "unescaped '\"'"); 40 | default -> buffer.append(c); 41 | } 42 | } 43 | case ESCAPE -> { 44 | switch (c) { 45 | case '\\' -> buffer.append('\\'); 46 | case '\'' -> buffer.append('\''); 47 | case '\"' -> buffer.append('\"'); 48 | case '0' -> buffer.append('\0'); 49 | case '1' -> buffer.append('\1'); 50 | case '2' -> buffer.append('\2'); 51 | case '3' -> buffer.append('\3'); 52 | case '4' -> buffer.append('\4'); 53 | case '5' -> buffer.append('\5'); 54 | case '6' -> buffer.append('\6'); 55 | case '7' -> buffer.append('\7'); 56 | case 'r' -> buffer.append('\r'); 57 | case 't' -> buffer.append('\t'); 58 | case 'f' -> buffer.append('\f'); 59 | case 'b' -> buffer.append('\b'); 60 | case 'n' -> buffer.append('\n'); 61 | case '&' -> buffer.append('&'); 62 | case '_' -> buffer.append(' '); 63 | case 'u' -> { 64 | mode = UNICODE; 65 | continue parse; 66 | } 67 | case ' ', '\t' -> { 68 | mode = SPACE; 69 | continue parse; 70 | } 71 | case '\r', '\n' -> { 72 | buffer.append(c); 73 | mode = SPACE; 74 | continue parse; 75 | } 76 | default -> throw new ParseException(input, row, col, "can't escape symbol " + c); 77 | } 78 | mode = CHAR; 79 | } 80 | case UNICODE -> { 81 | switch (c) { 82 | case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'a', 'b', 'c', 'd', 'e', 'f' -> { 83 | unicode.append(c); 84 | if (unicode.length() == 4) { 85 | char character = (char) Integer.parseInt(unicode.toString(), 16); 86 | buffer.append(character); 87 | unicode = new StringBuilder(); 88 | mode = CHAR; 89 | } 90 | } 91 | default -> { 92 | throw new ParseException(input, row, col, "unexpected hex character: " + c); 93 | } 94 | } 95 | } 96 | case SPACE -> { 97 | switch (c) { 98 | case '\t', '\r', ' ' -> {} 99 | case '\n' -> buffer.append(c); 100 | case '\\' -> mode = ESCAPE; 101 | case '\"' -> throw new ParseException(input, row, col, "unescaped '\"'"); 102 | default -> { 103 | buffer.append(c); 104 | mode = CHAR; 105 | } 106 | } 107 | } 108 | default -> throw new ParseException(input, row, col, "unknown"); 109 | } 110 | } 111 | if (mode == CHAR) return buffer.toString(); 112 | else throw new ParseException(input, row, col, "unexpected end of string"); 113 | } 114 | 115 | public static String wrap(String raw) { 116 | return raw 117 | .replace("\\", "\\\\") 118 | .replace("\n", "\\n") 119 | .replace("\b", "\\b") 120 | .replace("\r", "\\r") 121 | .replace("\t", "\\t") 122 | .replace("\f", "\\f") 123 | .replace("\"", "\\\"") 124 | .replace(" ", " \\_") 125 | .replace("&", "\\&") 126 | .replace(String.valueOf(ChatColor.COLOR_CHAR), "&") 127 | ; 128 | } 129 | 130 | public static String wrapToQuotes(String raw) { 131 | return "\""+wrap(raw)+"\""; 132 | } 133 | 134 | public static String wrapToQuotesIfNeeded(String raw) { 135 | if (raw.isEmpty()) return "\"\""; 136 | if (raw.matches("\\s")) return wrapToQuotes(raw); 137 | String wrapped = wrap(raw); 138 | if (wrapped.equals(raw)) return raw; 139 | return "\""+wrapped+"\""; 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/PowerNBT.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt; 2 | 3 | import me.dpohvar.powernbt.api.NBTManager; 4 | import me.dpohvar.powernbt.command.CommandNBT; 5 | import me.dpohvar.powernbt.completer.CompleterNBT; 6 | import me.dpohvar.powernbt.completer.TypeCompleter; 7 | import me.dpohvar.powernbt.listener.SelectListener; 8 | import me.dpohvar.powernbt.utils.*; 9 | import me.dpohvar.powernbt.utils.viewer.InteractiveViewer; 10 | import me.dpohvar.powernbt.utils.viewer.ViewerStyle; 11 | import org.bukkit.Bukkit; 12 | import org.bukkit.ChatColor; 13 | import org.bukkit.command.CommandSender; 14 | import org.bukkit.plugin.Plugin; 15 | import org.bukkit.plugin.java.JavaPlugin; 16 | 17 | import java.io.File; 18 | import java.nio.charset.Charset; 19 | import java.nio.charset.StandardCharsets; 20 | import java.util.HashMap; 21 | import java.util.List; 22 | 23 | public class PowerNBT extends JavaPlugin { 24 | 25 | private static final boolean SILENT = true; 26 | public static PowerNBT plugin; 27 | public static final Charset charset = StandardCharsets.UTF_8; 28 | private final HashMap callers = new HashMap(); 29 | private Translator translator; 30 | private static final Tokenizer tokenizer = new Tokenizer( 31 | null, null, null, List.of('\"'), null, List.of(' '), "{}[]()" 32 | ); 33 | private final String prefix = ChatColor.GOLD.toString() + ChatColor.BOLD + "[" + ChatColor.YELLOW + "PowerNBT" + ChatColor.GOLD + ChatColor.BOLD + "] " + ChatColor.RESET; 34 | private final String errorPrefix = ChatColor.DARK_RED.toString() + ChatColor.BOLD + "[" + ChatColor.RED + "PowerNBT" + ChatColor.DARK_RED + ChatColor.BOLD + "] " + ChatColor.RESET; 35 | private TypeCompleter typeCompleter; 36 | 37 | public PowerNBT() { 38 | super(); 39 | try { 40 | loadExtensions(); 41 | } catch (Error e) { 42 | e.printStackTrace(); 43 | } 44 | } 45 | 46 | private static void loadExtensions(){ 47 | try { 48 | Plugin varScript = Bukkit.getPluginManager().getPlugin("VarScript"); 49 | if (varScript != null) { 50 | Class bootHelperClazz = varScript.getClass().getClassLoader().loadClass("ru.dpohvar.varscript.boot.BootHelper"); 51 | ReflectionUtils.RefClass bootHelperFefClazz = ReflectionUtils.getRefClass(bootHelperClazz); 52 | ReflectionUtils.RefMethod loadExtensionsMethod = bootHelperFefClazz.getMethod("loadExtensions", ClassLoader.class); 53 | loadExtensionsMethod.call(PowerNBT.class.getClassLoader()); 54 | } 55 | } catch (ClassNotFoundException e) { 56 | e.printStackTrace(); 57 | } 58 | } 59 | 60 | /** 61 | * Get the folder where are stored saved files 62 | * 63 | * This files are used for command: /nbt $filename 64 | * @return folder 65 | */ 66 | public File getNBTFilesFolder() { 67 | return new File(getDataFolder(), "nbt"); 68 | } 69 | 70 | public Caller getCaller(CommandSender sender) { 71 | Caller c = callers.get(sender.getName()); 72 | if (c != null) { 73 | c.setOwner(sender); 74 | return c; 75 | } 76 | c = new Caller(sender); 77 | callers.put(sender.getName(), c); 78 | return c; 79 | } 80 | 81 | public File getLangFolder() { 82 | File lang = new File(getDataFolder(), "lang"); 83 | lang.mkdirs(); 84 | return lang; 85 | } 86 | 87 | public File getTemplateFolder() { 88 | File lang = new File(getDataFolder(), "templates"); 89 | lang.mkdirs(); 90 | return lang; 91 | } 92 | 93 | public Tokenizer getTokenizer() { 94 | return tokenizer; 95 | } 96 | 97 | public String getPrefix() { 98 | return prefix; 99 | } 100 | 101 | public String getErrorPrefix() { 102 | return errorPrefix; 103 | } 104 | 105 | /** 106 | * Get plugin debug mode 107 | * 108 | * @return true if plugin in debug mode 109 | */ 110 | public boolean isDebug() { 111 | return getConfig().getBoolean("debug"); 112 | } 113 | 114 | /** 115 | * Set plugin debug mode 116 | * 117 | * @param val true to enable debug mode 118 | */ 119 | public void setDebug(boolean val) { 120 | getConfig().set("debug", val); 121 | } 122 | 123 | public String translate(String key) { 124 | return translator.translate(key); 125 | } 126 | 127 | public String translate(String key, Object... values) { 128 | return translator.translate(key, values); 129 | } 130 | 131 | @Override 132 | public void onLoad() { 133 | plugin = this; 134 | } 135 | 136 | @Override 137 | public void onEnable() { 138 | String classMap = this.getConfig().getString("classmap"); 139 | if (classMap != null && !classMap.isEmpty()) { 140 | File classMapFile = new File(getDataFolder(),classMap); 141 | ReflectionUtils.addReplacementsYaml(classMapFile); 142 | } 143 | String lang = this.getConfig().getString("lang"); 144 | this.translator = new Translator(this, lang); 145 | this.typeCompleter = new TypeCompleter(getTemplateFolder()); 146 | getServer().getPluginManager().registerEvents(new SelectListener(), this); 147 | NBTStaticViewer.applyConfig(getConfig()); 148 | getCommand("powernbt").setExecutor(new CommandNBT()); 149 | getCommand("powernbt.").setExecutor(new CommandNBT(SILENT)); 150 | getCommand("powernbt").setTabCompleter(new CompleterNBT()); 151 | getCommand("powernbt.").setTabCompleter(new CompleterNBT()); 152 | } 153 | 154 | public TypeCompleter getTypeCompleter() { 155 | return typeCompleter; 156 | } 157 | 158 | private void printDebug(Object t){ 159 | if (isDebug()) getLogger().info("" + t); 160 | } 161 | 162 | /** 163 | * Get PowerNBT API 164 | * 165 | * @return api 166 | */ 167 | public static NBTManager getApi(){ 168 | return NBTManager.getInstance(); 169 | } 170 | } 171 | 172 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/nbt/NBTContainer.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.nbt; 2 | 3 | import me.dpohvar.powernbt.api.NBTBox; 4 | import me.dpohvar.powernbt.api.NBTCompound; 5 | import me.dpohvar.powernbt.exception.NBTTagNotFound; 6 | import me.dpohvar.powernbt.exception.NBTTagUnexpectedType; 7 | import me.dpohvar.powernbt.utils.PowerJSONParser; 8 | import me.dpohvar.powernbt.utils.StringParser; 9 | import me.dpohvar.powernbt.utils.query.NBTQuery; 10 | import org.apache.commons.lang.ArrayUtils; 11 | import org.apache.commons.lang.StringUtils; 12 | 13 | import java.util.ArrayList; 14 | import java.util.Collection; 15 | import java.util.List; 16 | import java.util.Map; 17 | 18 | import static me.dpohvar.powernbt.PowerNBT.plugin; 19 | 20 | // TODO: MAKE 21 | 22 | public abstract class NBTContainer { 23 | 24 | protected String selector = null; 25 | 26 | public NBTContainer(String selector) { 27 | this.selector = selector; 28 | } 29 | 30 | abstract public T getObject(); 31 | 32 | protected Object readCustomTag(){ 33 | return readTag(); 34 | } 35 | 36 | abstract protected Object readTag(); 37 | 38 | abstract protected void writeTag(Object value); 39 | 40 | protected void writeCustomTag(Object value){ 41 | writeTag(value); 42 | } 43 | 44 | protected void eraseTag() { 45 | writeTag(new NBTCompound()); 46 | } 47 | protected void eraseCustomTag() { 48 | eraseTag(); 49 | } 50 | 51 | abstract protected Class getContainerClass(); 52 | 53 | final public String getName(){ 54 | return getContainerClass().getSimpleName(); 55 | } 56 | 57 | public List getTypes() { 58 | return new ArrayList<>(); 59 | }; 60 | 61 | public String getSelector(){ 62 | return this.selector; 63 | }; 64 | 65 | public NBTQuery getSelectorQuery(){ 66 | return null; 67 | } 68 | /** 69 | * Set value of container root tag 70 | * @see #removeTag() remove tag if value is null 71 | * @param value root tag 72 | */ 73 | final public void setTag(Object value){ 74 | writeTag(value); 75 | } 76 | 77 | @Deprecated 78 | final public void setTag(NBTQuery query, Object value) throws NBTTagNotFound, NBTTagUnexpectedType { 79 | setTag(query.set(getTag(),value)); 80 | } 81 | 82 | /** 83 | * Set value of container root tag using PowerNBT options 84 | * @see #removeCustomTag() remove tag if value is null 85 | * @param value root tag 86 | */ 87 | final public void setCustomTag(Object value){ 88 | if (value instanceof NBTCompound tag){ 89 | NBTCompound tagClone = tag.clone(); 90 | List ignoreList = plugin.getConfig().getStringList("ignore_set."+getName()); 91 | if (!ignoreList.isEmpty()) { 92 | for (String ignore:ignoreList) tagClone.remove(ignore); 93 | value = tagClone; 94 | } 95 | } 96 | writeCustomTag(value); 97 | } 98 | 99 | @Deprecated 100 | final public void setCustomTag(NBTQuery query,Object value) throws NBTTagNotFound, NBTTagUnexpectedType { 101 | if (query.isEmpty()) setCustomTag(value); 102 | else setCustomTag(query.set(getCustomTag(),value)); 103 | } 104 | 105 | 106 | /** 107 | * Get root tag of container 108 | * @return NBT tag 109 | */ 110 | final public Object getTag(){ 111 | return readTag(); 112 | } 113 | 114 | @Deprecated 115 | final public Object getTag(NBTQuery query) throws NBTTagNotFound { 116 | return query.get(this.getTag()); 117 | } 118 | 119 | /** 120 | * Get root tag of container using PowerNBT options 121 | * @return NBT tag 122 | */ 123 | final public Object getCustomTag(){ 124 | Object value = readTag(); 125 | if (value instanceof NBTCompound tag){ 126 | NBTCompound tagClone = tag.clone(); 127 | List ignoreList = plugin.getConfig().getStringList("ignore_get."+getName()); 128 | if (!ignoreList.isEmpty()) { 129 | for (String ignore:ignoreList) tagClone.remove(ignore); 130 | value = tagClone; 131 | } 132 | } 133 | return value; 134 | } 135 | 136 | @Deprecated 137 | final public Object getCustomTag(NBTQuery query) throws NBTTagNotFound { 138 | return query.get(this.getCustomTag()); 139 | } 140 | 141 | /** 142 | * remove all NBT tags from container or remove contained object 143 | */ 144 | public final void removeTag(){ 145 | eraseTag(); 146 | } 147 | 148 | @Deprecated 149 | final public void removeTag(NBTQuery query) throws NBTTagNotFound { 150 | setTag(query.remove(this.getTag())); 151 | } 152 | 153 | /** 154 | * remove all NBT tags from container or remove contained object using PowerNBT options 155 | */ 156 | public final void removeCustomTag(){ 157 | eraseCustomTag(); 158 | } 159 | 160 | @Deprecated 161 | final public void removeCustomTag(NBTQuery query) throws NBTTagNotFound { 162 | if (query==null || query.isEmpty()) removeCustomTag(); 163 | else setCustomTag(query.remove(this.getCustomTag())); 164 | } 165 | 166 | public String toString(){ 167 | return getName(); 168 | } 169 | 170 | public static String parseValueToSelector(Object value, int maxLength){ 171 | String result = parseValueToSelector(value); 172 | if (result == null) return null; 173 | if (result.length() > maxLength) return null; 174 | return result; 175 | } 176 | 177 | public static String parseValueToSelector(Object value){ 178 | if (value == null) return "null"; 179 | if (value instanceof Boolean) return value+""; 180 | if (value instanceof Byte) return value+"b"; 181 | if (value instanceof Short) return value+"s"; 182 | if (value instanceof Integer) return value+"i"; 183 | if (value instanceof Long) return value+"l"; 184 | if (value instanceof Float) return value+"f"; 185 | if (value instanceof Double) return value+"d"; 186 | if (value instanceof String s) return "\"" + StringParser.wrap(s) + "\""; 187 | if (value instanceof byte[] array) return StringUtils.join(ArrayUtils.toObject(array), ',')+"b"; 188 | if (value instanceof int[] array) return StringUtils.join(ArrayUtils.toObject(array), ',')+"i"; 189 | if (value instanceof long[] array) return StringUtils.join(ArrayUtils.toObject(array), ',')+"l"; 190 | if (value instanceof NBTBox) return value.toString(); 191 | if (value instanceof Collection || value instanceof Map) return PowerJSONParser.stringify(value); 192 | return null; 193 | } 194 | 195 | public NBTContainer getRootContainer(){ 196 | return this; 197 | } 198 | 199 | public boolean isObjectReadonly(){ 200 | return false; 201 | } 202 | } 203 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/extension/NBTExtension.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.extension; 2 | 3 | import groovy.lang.Closure; 4 | import me.dpohvar.powernbt.api.NBTCompound; 5 | import me.dpohvar.powernbt.api.NBTList; 6 | import me.dpohvar.powernbt.api.NBTManager; 7 | import me.dpohvar.powernbt.extension.nbt.NBTCompoundProperties; 8 | import org.bukkit.Chunk; 9 | import org.bukkit.OfflinePlayer; 10 | import org.bukkit.block.Block; 11 | import org.bukkit.block.TileState; 12 | import org.bukkit.entity.Entity; 13 | import org.bukkit.inventory.ItemStack; 14 | 15 | import java.io.File; 16 | import java.io.IOException; 17 | import java.util.Collection; 18 | import java.util.Map; 19 | 20 | public class NBTExtension { 21 | 22 | // getter 23 | 24 | public static NBTCompound getNbt(Block self){ 25 | return NBTManager.getInstance().read(self); 26 | } 27 | 28 | public static NBTCompound getNbt(Entity self){ 29 | return NBTManager.getInstance().read(self); 30 | } 31 | 32 | public static NBTCompound getNbt(TileState self){ 33 | return NBTManager.getInstance().read(self); 34 | } 35 | 36 | public static NBTCompound getNbto(OfflinePlayer self){ 37 | return NBTManager.getInstance().readOfflinePlayer(self); 38 | } 39 | 40 | public static NBTCompound getNbt(Chunk self){ 41 | return NBTManager.getInstance().read(self); 42 | } 43 | 44 | public static NBTCompound getNbt(ItemStack self){ 45 | return NBTManager.getInstance().read(self); 46 | } 47 | 48 | public static Object getNbt(File self) throws IOException { 49 | return NBTManager.getInstance().read(self); 50 | } 51 | 52 | public static Object getNbtc(File self) throws IOException { 53 | return NBTManager.getInstance().readCompressed(self); 54 | } 55 | 56 | // setter 57 | 58 | public static void setNbt(Block self, NBTCompound data){ 59 | NBTManager.getInstance().write(self, data); 60 | } 61 | 62 | public static void setNbt(Entity self, NBTCompound data){ 63 | NBTManager.getInstance().write(self, data); 64 | } 65 | 66 | public static void setNbt(TileState self, NBTCompound data){ 67 | NBTManager.getInstance().write(self, data); 68 | } 69 | 70 | public static void setNbto(OfflinePlayer self, NBTCompound data){ 71 | NBTManager.getInstance().readOfflinePlayer(self); 72 | } 73 | 74 | public static void setNbt(Chunk self, NBTCompound data){ 75 | NBTManager.getInstance().write(self, data); 76 | } 77 | 78 | public static void setNbt(ItemStack self, NBTCompound data){ 79 | NBTManager.getInstance().write(self, data); 80 | } 81 | 82 | public static void setNbt(File self, Object data) throws IOException { 83 | NBTManager.getInstance().write(self, data); 84 | } 85 | 86 | public static void setNbtc(File self, Object data) throws IOException { 87 | NBTManager.getInstance().readCompressed(self); 88 | } 89 | 90 | // accessor 91 | 92 | public static Object nbt(T self, Closure modifier){ 93 | NBTCompound tag = getNbt(self); 94 | NBTCompound ext = tag != null ? tag.clone() : new NBTCompound(); 95 | modifier.setDelegate(new NBTCompoundProperties(ext)); 96 | modifier.setResolveStrategy(Closure.DELEGATE_FIRST); 97 | Object result = modifier.call(self); 98 | if (!ext.equals(tag)) setNbt(self, ext); 99 | return result; 100 | } 101 | 102 | public static Object nbt(T self, Closure modifier){ 103 | NBTCompound tag = getNbt(self); 104 | NBTCompound ext = tag != null ? tag.clone() : new NBTCompound(); 105 | modifier.setDelegate(new NBTCompoundProperties(ext)); 106 | modifier.setResolveStrategy(Closure.DELEGATE_FIRST); 107 | Object result = modifier.call(self); 108 | if (!ext.equals(tag)) setNbt(self, ext); 109 | return result; 110 | } 111 | 112 | public static Object nbt(T self, Closure modifier){ 113 | NBTCompound tag = getNbt(self); 114 | NBTCompound ext = tag != null ? tag.clone() : new NBTCompound(); 115 | modifier.setDelegate(new NBTCompoundProperties(ext)); 116 | modifier.setResolveStrategy(Closure.DELEGATE_FIRST); 117 | Object result = modifier.call(self); 118 | if (!ext.equals(tag)) setNbt(self, ext); 119 | return result; 120 | } 121 | 122 | public static Object nbt(T self, Closure modifier){ 123 | NBTCompound tag = getNbt(self); 124 | NBTCompound ext = tag != null ? tag.clone() : new NBTCompound(); 125 | modifier.setDelegate(new NBTCompoundProperties(ext)); 126 | modifier.setResolveStrategy(Closure.DELEGATE_FIRST); 127 | Object result = modifier.call(self); 128 | if (!ext.equals(tag)) setNbt(self, ext); 129 | return result; 130 | } 131 | 132 | public static Object nbt(T self, Closure modifier){ 133 | NBTCompound tag = getNbt(self); 134 | NBTCompound ext = tag != null ? tag.clone() : new NBTCompound(); 135 | modifier.setDelegate(new NBTCompoundProperties(ext)); 136 | modifier.setResolveStrategy(Closure.DELEGATE_FIRST); 137 | Object result = modifier.call(self); 138 | if (!ext.equals(tag)) setNbt(self, ext); 139 | return result; 140 | } 141 | 142 | public static Object nbt(T self, Closure modifier) throws IOException { 143 | NBTCompound tag = (NBTCompound) getNbt(self); 144 | NBTCompound ext = tag != null ? tag.clone() : new NBTCompound(); 145 | modifier.setDelegate(new NBTCompoundProperties(ext)); 146 | modifier.setResolveStrategy(Closure.DELEGATE_FIRST); 147 | Object result = modifier.call(self); 148 | if (!ext.equals(tag)) setNbt(self, ext); 149 | return result; 150 | } 151 | 152 | public static Object nbto(T self, Closure modifier) throws IOException { 153 | NBTCompound tag = getNbto(self); 154 | NBTCompound ext = tag != null ? tag.clone() : new NBTCompound(); 155 | modifier.setDelegate(new NBTCompoundProperties(ext)); 156 | modifier.setResolveStrategy(Closure.DELEGATE_FIRST); 157 | Object result = modifier.call(self); 158 | if (!ext.equals(tag)) setNbto(self, ext); 159 | return result; 160 | } 161 | 162 | public static Object nbtc(T self, Closure modifier) throws IOException { 163 | NBTCompound tag = (NBTCompound) getNbtc(self); 164 | NBTCompound ext = tag != null ? tag.clone() : new NBTCompound(); 165 | modifier.setDelegate(new NBTCompoundProperties(ext)); 166 | modifier.setResolveStrategy(Closure.DELEGATE_FIRST); 167 | Object result = modifier.call(self); 168 | if (!ext.equals(tag)) setNbtc(self, ext); 169 | return result; 170 | } 171 | 172 | public static NBTCompound toNBT(Map self) throws IOException { 173 | if (self instanceof NBTCompound cmp) return cmp; 174 | return new NBTCompound(self); 175 | } 176 | 177 | public static NBTList toNBT(Collection self) throws IOException { 178 | if (self instanceof NBTList cmp) return cmp; 179 | return new NBTList(self); 180 | } 181 | 182 | } 183 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | 8 | false 9 | 10 | DPOH-VAR 11 | https://github.com/flinbein/powernbt 12 | Powerful nbt editor for bukkit 13 | 14 | 17 15 | 16 | 1.17 17 | 1.15.2-R0.1-SNAPSHOT 18 | 1.17.1-R0.1-SNAPSHOT 19 | 3.0.9 20 | DEV-SNAPSHOT 21 | 22 | github 23 | UTF-8 24 | 25 | 26 | 27 | 28 | DPOH-VAR 29 | dpohvar@gmail.com 30 | https://github.com/DPOH-VAR 31 | 32 | 33 | 34 | me.dpohvar.powernbt 35 | powernbt 36 | ${plugin-version} 37 | jar 38 | 39 | Powerful NBT editor for CraftBukkit 1.5 and later 40 | https://www.spigotmc.org/resources/powernbt.9098/ 41 | 42 | 43 | https://github.com/flinbein/powernbt/releases 44 | 45 | codemc-releases 46 | https://repo.codemc.io/repository/maven-releases/ 47 | 48 | 49 | codemc-snapshots 50 | https://repo.codemc.io/repository/maven-snapshots/ 51 | 52 | 53 | 54 | 55 | 56 | spigot-repo 57 | https://hub.spigotmc.org/nexus/content/repositories/snapshots/ 58 | 59 | 60 | 61 | 62 | 63 | org.spigotmc 64 | spigot-api 65 | ${spigot-version} 66 | provided 67 | 68 | 69 | org.bukkit 70 | bukkit 71 | ${bukkit-version} 72 | provided 73 | 74 | 75 | org.jetbrains 76 | annotations 77 | RELEASE 78 | compile 79 | 80 | 81 | org.codehaus.groovy 82 | groovy-all 83 | ${groovy-version} 84 | pom 85 | provided 86 | 87 | 88 | org.junit.jupiter 89 | junit-jupiter-engine 90 | 5.7.2 91 | test 92 | 93 | 94 | 95 | 96 | ${project.artifactId} 97 | 98 | src/test/java 99 | 100 | 101 | 102 | src/main/resources 103 | true 104 | 105 | 106 | 107 | 108 | 109 | org.apache.maven.plugins 110 | maven-compiler-plugin 111 | 3.8.1 112 | 113 | ${java-version} 114 | ${java-version} 115 | 116 | 117 | 118 | 119 | org.apache.maven.plugins 120 | maven-surefire-plugin 121 | 2.22.2 122 | 123 | 124 | 125 | org.apache.maven.plugins 126 | maven-javadoc-plugin 127 | 2.10.4 128 | 129 | doc 130 | public 131 | 132 | 133 | 134 | 135 | com.github.github 136 | site-maven-plugin 137 | 0.11 138 | 139 | PowerNBT 140 | DPOH-VAR 141 | Creating site for ${plugin-version} 142 | 143 | 144 | 145 | 146 | site 147 | 148 | site 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | org.apache.maven.plugins 160 | maven-javadoc-plugin 161 | 2.10.4 162 | 163 | 164 | ${project.reporting.outputDirectory} 165 | ${basedir}/src/main/javadoc/stylesheet.css 166 | 167 | 168 | org.bukkit 169 | bukkit 170 | ${bukkit-version} 171 | provided 172 | 173 | 174 | UTF-8 175 | true 176 | UTF-8 177 | public 178 | 179 | http://jd.bukkit.org/dev/apidocs 180 | 181 | 182 | me/dpohvar/powernbt/PowerNBT.java 183 | me/dpohvar/powernbt/api/*.java 184 | 185 | 186 | 187 | 188 | 189 | 190 | -------------------------------------------------------------------------------- /src/main/java/me/dpohvar/powernbt/utils/viewer/components/FooterElement.java: -------------------------------------------------------------------------------- 1 | package me.dpohvar.powernbt.utils.viewer.components; 2 | 3 | import com.google.common.base.Strings; 4 | import me.dpohvar.powernbt.api.NBTManagerUtils; 5 | import me.dpohvar.powernbt.utils.viewer.ContainerControl; 6 | import me.dpohvar.powernbt.utils.viewer.EventBuilder; 7 | import me.dpohvar.powernbt.utils.viewer.ViewerStyle; 8 | import net.md_5.bungee.api.ChatColor; 9 | import net.md_5.bungee.api.chat.BaseComponent; 10 | import net.md_5.bungee.api.chat.HoverEvent; 11 | import net.md_5.bungee.api.chat.TextComponent; 12 | import net.md_5.bungee.api.chat.hover.content.Text; 13 | import org.apache.commons.lang.StringUtils; 14 | 15 | import java.util.*; 16 | import java.util.stream.Stream; 17 | 18 | public class FooterElement implements Element { 19 | 20 | private final TextComponent component; 21 | 22 | public FooterElement(ViewerStyle style, ContainerControl control, int colLimit, int rowLimit, int start, int end, boolean hex, boolean bin){ 23 | TextComponent result = new TextComponent(""); 24 | 25 | String parentAccess = getParentAccess(start, end, hex, bin); 26 | ChatColor barColor = style.getColor("buttons.bar"); 27 | Object value = control.getValue(); 28 | 29 | // valueClass 30 | String valueTypeName = value == null ? "null" : value.getClass().getSimpleName(); 31 | TextComponent typeNameCmp = new TextComponent(valueTypeName+" "); 32 | typeNameCmp.setColor(style.getColorByValue(value)); 33 | result.addExtra(typeNameCmp); 34 | 35 | // buttons 36 | List buttonElements = Stream.of( 37 | ButtonUpdate.create(style, control, parentAccess), 38 | ButtonSelectJson.create(style, control), 39 | ButtonCopyToBuffer.create(style, control), 40 | ButtonPasteFromBuffer.create(style, control), 41 | ButtonCopyToClipboard.create(style, control), 42 | ButtonEdit.create(style, control), 43 | ButtonRemove.create(style, control, null) 44 | ).filter(Objects::nonNull).toList(); 45 | 46 | if (buttonElements.size() > 0) { 47 | result.addExtra(barColor+"["); 48 | boolean firstButton = true; 49 | for (InteractiveElement buttonElement : buttonElements) { 50 | if (!firstButton) result.addExtra(barColor+"|"); 51 | firstButton = false; 52 | result.addExtra(buttonElement.getComponent()); 53 | } 54 | result.addExtra(barColor+"] "); 55 | } 56 | 57 | // pages 58 | int size = -1; 59 | if (value instanceof Map map) size = map.size(); 60 | else if (value instanceof String s) size = s.length(); 61 | else if (value instanceof Collection c) size = c.size(); 62 | else { 63 | Object[] objects = NBTManagerUtils.convertToObjectArrayOrNull(value); 64 | if (objects != null) size = objects.length; 65 | } 66 | if (size >= 0) { 67 | TextComponent paginatorCmp = new TextComponent(""); 68 | if (start == 0 && end == 0) end = (value instanceof String) ? colLimit * rowLimit : colLimit; 69 | 70 | int pageSize = end - start; 71 | 72 | paginatorCmp.setColor(style.getColor("paginator.text")); 73 | 74 | TextComponent btnLeftComponent = new TextComponent(style.getIcon("paginator.prev")); 75 | btnLeftComponent.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text("navigate to previous page"))); 76 | if (start > 0 && !control.isReadonly()) { 77 | btnLeftComponent.setColor(style.getColor("paginator.navActive")); 78 | btnLeftComponent.setBold(true); 79 | int pStart = start - pageSize; 80 | if (pStart < 0) pStart = 0; 81 | int pEnd = pStart + pageSize; 82 | //btnLeftComponent.setClickEvent(runOnClick(getViewCommand(selector, query, pStart, pEnd, hex, bin), false)); 83 | String pageParentAccess = getParentAccess(pStart, pEnd, hex, bin); 84 | btnLeftComponent.setClickEvent(EventBuilder.runNbt(control.getSelectorWithQuery()+ " "+pageParentAccess, false)); 85 | } else { 86 | btnLeftComponent.setColor(style.getColor("paginator.nav")); 87 | } 88 | 89 | if (start == 0 && end >= size) { // full listed 90 | result.addExtra("["+size+"]"); 91 | } else if (start >= size) { // out of range 92 | StringBuilder builder = new StringBuilder(); 93 | paginatorCmp.addExtra("["); 94 | paginatorCmp.addExtra(btnLeftComponent); 95 | 96 | TextComponent errorCmp = new TextComponent(" out of range "+size); 97 | errorCmp.setColor(style.getColor("paginator.errorText")); 98 | paginatorCmp.addExtra(errorCmp); 99 | paginatorCmp.addExtra(size + " ]"); 100 | } else { 101 | var pow = (int) Math.ceil(Math.log10(size)); 102 | String startText = pow == 0 ? String.valueOf(start) : Strings.padStart(String.valueOf(start), pow, '0'); 103 | String endText = pow == 0 ? String.valueOf(end) : Strings.padStart(String.valueOf(end), pow, '0'); 104 | 105 | paginatorCmp.addExtra("["); 106 | paginatorCmp.addExtra(btnLeftComponent); 107 | paginatorCmp.addExtra(" "+startText+"-"+endText+" "); 108 | 109 | TextComponent btnRightComponent = new TextComponent(style.getIcon("paginator.next")); 110 | btnRightComponent.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text("navigate to next page"))); 111 | if (end < size) { 112 | btnRightComponent.setColor(style.getColor("paginator.navActive")); 113 | btnRightComponent.setBold(true); 114 | int pStart = start + pageSize; 115 | int pEnd = pStart + pageSize; 116 | String pageParentAccess = getParentAccess(pStart, pEnd, hex, bin); 117 | btnRightComponent.setClickEvent(EventBuilder.runNbt(control.getSelectorWithQuery()+ " "+pageParentAccess, false)); 118 | } else { 119 | btnRightComponent.setColor(style.getColor("paginator.nav")); 120 | } 121 | paginatorCmp.addExtra(btnRightComponent); 122 | paginatorCmp.addExtra(" / "); 123 | 124 | TextComponent btnTotalComponent = new TextComponent(String.valueOf(size)); 125 | btnTotalComponent.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text("show all values"))); 126 | String fullPageParentAccess = getParentAccess(0, Integer.MAX_VALUE, hex, bin); 127 | btnTotalComponent.setClickEvent(EventBuilder.runNbt(control.getSelectorWithQuery()+ " "+fullPageParentAccess, false)); 128 | btnTotalComponent.setColor(style.getColor("paginator.navActive")); 129 | 130 | paginatorCmp.addExtra(btnTotalComponent); 131 | 132 | paginatorCmp.addExtra("]"); 133 | 134 | 135 | } 136 | 137 | result.addExtra(paginatorCmp); 138 | } 139 | 140 | 141 | this.component = result; 142 | } 143 | 144 | String getParentAccess(int start, int end, boolean hex, boolean bin){ 145 | List list = new ArrayList<>(); 146 | if (start == 0 && end == Integer.MAX_VALUE) { 147 | list.add("a"); 148 | } else if (start != 0 || end != 0) { 149 | list.add(start+"-"+end); 150 | } 151 | if (hex) list.add("h"); 152 | if (bin) list.add("b"); 153 | return StringUtils.join(list,","); 154 | } 155 | 156 | @Override 157 | public BaseComponent getComponent() { 158 | return component; 159 | } 160 | } 161 | --------------------------------------------------------------------------------