Don't jarjar anymore.

This commit is contained in:
zontreck 2024-10-09 22:21:30 -07:00
parent 44eb9d1d9c
commit 307b3427e8
77 changed files with 6359 additions and 15 deletions

View file

@ -11,13 +11,6 @@ base {
archivesName = project.archives_name
}
configurations {
provided
compile.extendsFrom(provided)
implementation.extendsFrom(provided)
minecraftLibrary.extendsFrom(provided)
}
loom {
silentMojangMappingsLicense()
@ -43,10 +36,6 @@ dependencies {
minecraft "net.minecraft:minecraft:$project.minecraft_version"
mappings loom.officialMojangMappings()
forge "net.minecraftforge:forge:$project.forge_version"
provided "dev.zontreck:LibAC:${libac}"
provided "dev.zontreck:EventsBus:${eventsbus}"
}
processResources {
@ -72,10 +61,6 @@ tasks.withType(JavaCompile).configureEach {
it.options.release = 17
}
tasks.named('jar', Jar).configure {
from {
configurations.provided.asFileTree.collect { zipTree(it) }
}
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
manifest {
attributes([

View file

@ -0,0 +1,106 @@
package dev.zontreck.ariaslib.args;
import dev.zontreck.ariaslib.exceptions.WrongArgumentTypeException;
public abstract class Argument<T> implements Cloneable
{
public boolean hasValue = false;
public String name;
/**
* Initializes a boolean only command line toggle
*
* @param name The option name
*/
public Argument(String name) {
this.name = name;
}
/**
* Retrieves the current argument's type
*
* @return The argument type!
*/
public abstract ArgumentType getType();
/**
* Retrieves the value.
*
* @return The value
* @throws IllegalArgumentException When there is no value
*/
public T getValue() throws IllegalArgumentException {
throw new IllegalArgumentException("No value");
}
/**
* Directly cast to the Argument type Long
* @return
* @throws WrongArgumentTypeException Throws when type does not match
*/
public LongArgument getAsLong() throws WrongArgumentTypeException {
if(this instanceof LongArgument)
{
return (LongArgument) this;
}
throw new WrongArgumentTypeException();
}
/**
* Directly cast to the Argument type String
* @return
* @throws WrongArgumentTypeException Throws when type does not match
*/
public StringArgument getAsString() throws WrongArgumentTypeException {
if(this instanceof StringArgument)
{
return (StringArgument) this;
}
throw new WrongArgumentTypeException();
}
/**
* Directly cast to the Argument type Integer
* @return
* @throws WrongArgumentTypeException Throws when type does not match
*/
public IntegerArgument getAsInteger() throws WrongArgumentTypeException
{
if(this instanceof IntegerArgument)
{
return (IntegerArgument) this;
}
throw new WrongArgumentTypeException();
}
@Override
public Argument<T> clone() {
Argument<T> arg = null;
try{
if(getType() == ArgumentType.LONG)
{
arg = (Argument<T>) new LongArgument(name, getAsLong().getValue());
} else if(getType() == ArgumentType.STRING)
{
arg = (Argument<T>) new StringArgument(name, getAsString().getValue());
} else if(getType() == ArgumentType.BOOLEAN) {
arg = (Argument<T>) new BooleanArgument(name);
} else if(getType() == ArgumentType.INTEGER){
arg = (Argument<T>) new IntegerArgument(name, getAsInteger().getValue());
}
}catch (WrongArgumentTypeException ex)
{
ex.printStackTrace();
}
return arg;
}
}

View file

@ -0,0 +1,25 @@
package dev.zontreck.ariaslib.args;
public enum ArgumentType {
/**
* This indicates a string. It may possibly have a default value
*/
STRING,
/**
* This indicates a boolean
* <p>
* This may have a default value, which initiates a BooleanArgument
*/
BOOLEAN,
/**
* This indicates a data type of integer
* The type of integer arg is determined by the length of the integer.
*/
INTEGER,
/**
* This is a long value, which can hold larger values than a integer. The type of integer arg is determined by the length of the integer.
*/
LONG
}

View file

@ -0,0 +1,63 @@
package dev.zontreck.ariaslib.args;
import java.util.HashMap;
import java.util.Map;
public class Arguments implements Cloneable
{
private Map<String, Argument<?>> args = new HashMap<>();
/**
* Set the argument in the args list
* @param arg
*/
public void setArg(Argument arg) {
args.put(arg.name, arg);
}
/**
* Checks for and returns the argument
*
* @param argName The argument's name
* @return The argument instance, or null if not found
*/
public Argument getArg(String argName) {
if (hasArg(argName))
return args.get(argName);
else return null;
}
/**
* Checks if the argument is set.
*
* @param argName The argument's name to check for
* @return True if the argument is present. This does not indicate if the argument has a value
*/
public boolean hasArg(String argName) {
return args.containsKey(argName);
}
/**
* Checks the argument (if it exists), for whether a value is set
*
* @param argName This is the argument name
* @return True if a value is set
* @throws IllegalArgumentException If there is no such argument
*/
public boolean argHasValue(String argName) throws IllegalArgumentException {
if (hasArg(argName)) {
return getArg(argName).hasValue;
} else throw new IllegalArgumentException(("No such argument"));
}
@Override
public Arguments clone() {
Arguments arg = new Arguments();
for(Map.Entry<String, Argument<?>> entry : args.entrySet())
{
arg.setArg(entry.getValue().clone());
}
return arg;
}
}

View file

@ -0,0 +1,20 @@
package dev.zontreck.ariaslib.args;
public class ArgumentsBuilder {
private Arguments args = new Arguments();
public static ArgumentsBuilder builder() {
return new ArgumentsBuilder();
}
public ArgumentsBuilder withArgument(Argument arg) {
args.setArg(arg);
return this;
}
public Arguments build()
{
return args;
}
}

View file

@ -0,0 +1,99 @@
package dev.zontreck.ariaslib.args;
public class ArgumentsParser {
/**
* Parses and returns the arguments list with keeping defaults in mind
* @param args
* @param defaults
* @return Arguments with defaults set
*/
public static Arguments parseArguments(String[] args, Arguments defaults) {
Arguments arguments = defaults.clone();
for (int i = 0; i < args.length; i++) {
Argument arg = parseArgument(args[i]);
if (arg != null) {
Argument defaultArg = null;
if (defaults.hasArg(arg.name)) {
defaultArg = defaults.getArg(arg.name);
}
if (!arg.hasValue) {
if (defaultArg != null) {
arg = defaultArg;
}
}
arguments.setArg(arg);
}
}
return arguments;
}
/**
* Parses and returns an argument with a type set
* @param arg The argument to parse with double tack
* @return Typed Argument
* @throws IllegalArgumentException when no type matches and the input is malformed in some way
*/
public static Argument parseArgument(String arg) {
if (arg.startsWith("--")) {
String[] parts = arg.split("=");
String name = getNamePart(parts[0]);
if (parts.length == 1) {
return new BooleanArgument(name);
} else if (parts.length == 2) {
String value = getValuePart(parts[1]);
ArgumentType typeOfArg = getArgumentType(value);
switch(typeOfArg)
{
case INTEGER:
{
return new IntegerArgument(name, Integer.parseInt(value));
}
case LONG:
{
return new LongArgument(name, Long.parseLong(value));
}
case BOOLEAN:
{
return new BooleanArgument(name);
}
default:
{
return new StringArgument(name, value);
}
}
} else throw new IllegalArgumentException("The argument is malformed. Remember to use --arg=val, or --toggle");
} else {
throw new IllegalArgumentException("Not a valid argument format");
}
}
protected static String getNamePart(String entry) {
return entry.substring(2);
}
protected static String getValuePart(String entry) {
return entry;
}
protected static ArgumentType getArgumentType(String input) {
try {
Integer.parseInt(input);
return ArgumentType.INTEGER;
}catch(Exception e){}
try{
Long.parseLong(input);
return ArgumentType.LONG;
}catch(Exception E){
}
if(input.isEmpty())
return ArgumentType.BOOLEAN;
else return ArgumentType.STRING;
}
}

View file

@ -0,0 +1,35 @@
package dev.zontreck.ariaslib.args;
public class BooleanArgument extends Argument<Boolean> {
private boolean value;
/**
* Initializes a boolean only command line toggle
*
* @param name The option name
*/
public BooleanArgument(String name) {
super(name);
this.hasValue = true;
this.value = true;
}
@Override
public Boolean getValue() {
return value;
}
@Override
public ArgumentType getType() {
return ArgumentType.BOOLEAN;
}
@Override
public String toString() {
return "BooleanArgument{" +
name + "=true" +
'}';
}
}

View file

@ -0,0 +1,30 @@
package dev.zontreck.ariaslib.args;
public class IntegerArgument extends Argument<Integer> {
private int value;
public IntegerArgument(String name, int value) {
super(name);
this.hasValue = true;
this.value = value;
}
@Override
public ArgumentType getType() {
return ArgumentType.INTEGER;
}
@Override
public Integer getValue() {
return value;
}
@Override
public String toString() {
return "IntegerArgument{" +
name + "=" +
value +
'}';
}
}

View file

@ -0,0 +1,30 @@
package dev.zontreck.ariaslib.args;
public class LongArgument extends Argument<Long> {
private long value;
public LongArgument(String name, long value) {
super(name);
this.hasValue = true;
this.value = value;
}
@Override
public ArgumentType getType() {
return ArgumentType.LONG;
}
@Override
public Long getValue() {
return value;
}
@Override
public String toString() {
return "LongArgument{" +
name + "=" +
value +
'}';
}
}

View file

@ -0,0 +1,30 @@
package dev.zontreck.ariaslib.args;
public class StringArgument extends Argument<String> {
private String value;
public StringArgument(String name, String value) {
super(name);
this.value = value;
this.hasValue = true;
}
@Override
public String getValue() {
return value;
}
@Override
public ArgumentType getType() {
return ArgumentType.STRING;
}
@Override
public String toString() {
return "StringArgument{" +
name + "=" +
value +
'}';
}
}

View file

@ -0,0 +1,7 @@
package dev.zontreck.ariaslib.exceptions;
public class EventRegistrationException extends Exception{
public EventRegistrationException(String message){
super(message);
}
}

View file

@ -0,0 +1,7 @@
package dev.zontreck.ariaslib.exceptions;
public class WrongArgumentTypeException extends Exception
{
}

View file

@ -0,0 +1,34 @@
package dev.zontreck.ariaslib.file;
import java.io.*;
import java.nio.file.Path;
import java.nio.file.Paths;
public class AriaIO {
public static void write(Path fileName, Entry folder) {
try {
DataOutputStream dos = new DataOutputStream(new FileOutputStream(fileName.toFile()));
folder.write(dos);
dos.close();
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static Entry read(Path fileName) {
try {
DataInputStream dis = new DataInputStream(new FileInputStream(fileName.toFile()));
return Entry.read(dis);
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static Path resolveDataFile(String main) {
return Paths.get(main + ".aria");
}
}

View file

@ -0,0 +1,281 @@
package dev.zontreck.ariaslib.file;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* An entry in the serialized file
*/
public class Entry<K> {
public static final byte YES = 1;
public static final byte NO = 0;
public EntryType type;
public String name;
public K value;
public Entry(K v, String name) {
value = v;
this.name = name;
if (v instanceof String) {
type = EntryType.STRING;
} else if (v instanceof Integer) {
type = EntryType.INT;
} else if (v instanceof List<?>) {
type = EntryType.FOLDER;
} else if (v instanceof Boolean) {
type = EntryType.BOOL;
} else if (v instanceof Long) {
type = EntryType.LONG;
} else if (v instanceof Short) {
type = EntryType.SHORT;
} else if (v instanceof Byte) {
type = EntryType.BYTE;
} else if (v instanceof Double) {
type = EntryType.DOUBLE;
} else if (v instanceof Float) {
type = EntryType.FLOAT;
} else if (v instanceof int[]) {
type = EntryType.INT_ARRAY;
} else if (v instanceof String[]) {
type = EntryType.STRING_ARRAY;
} else if (v instanceof byte[]) {
type = EntryType.BYTE_ARRAY;
} else if (v instanceof long[]) {
type = EntryType.LONG_ARRAY;
} else {
type = EntryType.INVALID;
}
}
private Entry() {
}
public static Entry read(DataInputStream dis) throws IOException {
EntryType et = EntryType.of(dis.readByte());
int nameLen = dis.readInt();
byte[] nm = new byte[nameLen];
for (int i = 0; i < nameLen; i++) {
nm[i] = dis.readByte();
}
Entry work = new Entry<>();
work.type = et;
work.name = new String(nm);
//System.out.println("Read start: " + work.name + " [ " + work.type.toString() + " ]");
switch (et) {
case FOLDER: {
Entry<List<Entry>> entries = (Entry<List<Entry>>) work;
entries.value = new ArrayList<>();
int numEntries = dis.readInt();
for (int i = 0; i < numEntries; i++) {
entries.value.add(Entry.read(dis));
}
break;
}
case STRING: {
Entry<String> w = (Entry<String>) work;
int vLen = dis.readInt();
byte[] x = new byte[vLen];
for (int i = 0; i < vLen; i++) {
x[i] = dis.readByte();
}
w.value = new String(x);
break;
}
case INT: {
Entry<Integer> w = (Entry<Integer>) work;
w.value = dis.readInt();
break;
}
case BOOL: {
Entry<Boolean> w = (Entry<Boolean>) work;
byte b = dis.readByte();
if (b == YES) w.value = true;
else w.value = false;
break;
}
case LONG: {
Entry<Long> w = (Entry<Long>) work;
w.value = dis.readLong();
break;
}
case SHORT: {
Entry<Short> w = (Entry<Short>) work;
w.value = dis.readShort();
break;
}
case BYTE: {
Entry<Byte> w = (Entry<Byte>) work;
w.value = dis.readByte();
break;
}
case DOUBLE: {
Entry<Double> w = (Entry<Double>) work;
w.value = dis.readDouble();
break;
}
case FLOAT: {
Entry<Float> w = (Entry<Float>) work;
w.value = dis.readFloat();
break;
}
case INT_ARRAY: {
Entry<int[]> w = (Entry<int[]>) work;
int num = dis.readInt();
w.value = new int[num];
for (int i = 0; i < num; i++) {
w.value[i] = dis.readInt();
}
break;
}
case STRING_ARRAY: {
Entry<String[]> w = (Entry<String[]>) work;
int num = dis.readInt();
w.value = new String[num];
for (int i = 0; i < num; i++) {
int len = dis.readInt();
byte[] bStr = new byte[len];
for (int j = 0; j < len; j++) {
bStr[j] = dis.readByte();
}
w.value[i] = new String(bStr);
}
break;
}
case BYTE_ARRAY: {
Entry<byte[]> w = (Entry<byte[]>) work;
int num = dis.readInt();
w.value = new byte[num];
for (int i = 0; i < num; i++) {
w.value[i] = dis.readByte();
}
break;
}
case LONG_ARRAY: {
Entry<long[]> w = (Entry<long[]>) work;
int num = dis.readInt();
w.value = new long[num];
for (int i = 0; i < num; i++) {
w.value[i] = dis.readLong();
}
break;
}
}
//System.out.println("Read finished: " + work.name + " [ " + work.type.toString() + " ]");
return work;
}
public void write(DataOutputStream dos) throws IOException {
dos.writeByte((int) type.value);
byte[] nameBytes = name.getBytes();
dos.writeInt(nameBytes.length);
dos.write(nameBytes);
switch (type) {
case FOLDER: {
List<Entry<?>> entries = (List<Entry<?>>) value;
dos.writeInt(entries.size());
for (Entry<?> x :
entries) {
x.write(dos);
}
break;
}
case STRING: {
String s = (String) value;
byte[] bS = s.getBytes();
dos.writeInt(bS.length);
dos.write(bS);
break;
}
case INT: {
dos.writeInt((Integer) value);
break;
}
case BOOL: {
boolean x = (Boolean) value;
if (x) dos.writeByte(YES);
else dos.writeByte(NO);
break;
}
case LONG: {
dos.writeLong((Long) value);
break;
}
case SHORT: {
dos.writeShort((Short) value);
break;
}
case BYTE: {
dos.write((Byte) value);
break;
}
case DOUBLE: {
dos.writeDouble((Double) value);
break;
}
case FLOAT: {
dos.writeFloat((Float) value);
break;
}
case INT_ARRAY: {
int[] arr = (int[]) value;
dos.writeInt(arr.length);
for (int x : arr
) {
dos.writeInt(x);
}
break;
}
case STRING_ARRAY: {
String[] arr = (String[]) value;
dos.writeInt(arr.length);
for (String s : arr) {
byte[] bArr = s.getBytes();
dos.writeInt(bArr.length);
dos.write(bArr);
}
break;
}
case BYTE_ARRAY: {
byte[] arr = (byte[]) value;
dos.writeInt(arr.length);
for (byte b : arr) {
dos.write(b);
}
break;
}
case LONG_ARRAY: {
long[] arr = (long[]) value;
dos.writeInt(arr.length);
for (long L : arr) {
dos.writeLong(L);
}
break;
}
}
}
}

View file

@ -0,0 +1,36 @@
package dev.zontreck.ariaslib.file;
import java.util.Arrays;
import java.util.stream.Collectors;
public enum EntryType {
FOLDER(0),
STRING(1),
INT(2),
BOOL(3),
LONG(4),
SHORT(5),
BYTE(6),
DOUBLE(7),
FLOAT(8),
INT_ARRAY(9),
STRING_ARRAY(10),
BYTE_ARRAY(11),
LONG_ARRAY(12),
INVALID(255);
public byte value;
EntryType(int v)
{
value = (byte)v;
}
public static EntryType of(byte b)
{
return Arrays.stream(values())
.filter(c->c.value == b)
.collect(Collectors.toList())
.get(0);
}
}

View file

@ -0,0 +1,118 @@
package dev.zontreck.ariaslib.file;
import java.util.UUID;
public class EntryUtils {
public static Entry mkStr(String name, String value)
{
return new Entry<String>(value, name);
}
public static String getStr(Entry e)
{
Entry<String> eS = (Entry<String>) e;
return eS.value;
}
public static Entry mkInt(String name, int value)
{
return new Entry<Integer>(value, name);
}
public static int getInt(Entry e)
{
Entry<Integer> eS = (Entry<Integer>) e;
return eS.value;
}
public static Entry mkBool(String name, boolean value)
{
return new Entry<Boolean>(value, name);
}
public static boolean getBool(Entry e)
{
Entry<Boolean> eS = (Entry<Boolean>) e;
return eS.value;
}
public static Entry mkLong(String name, long value)
{
return new Entry<Long>(value, name);
}
public static long getLong(Entry e)
{
Entry<Long> eS = (Entry<Long>) e;
return eS.value;
}
public static Entry mkShort(String name, short value)
{
return new Entry<Short>(value, name);
}
public static short getShort(Entry e)
{
Entry<Short> eS = (Entry<Short>) e;
return eS.value;
}
public static Entry mkByte(String name, byte value)
{
return new Entry<Byte>(value, name);
}
public static byte getByte(Entry e)
{
Entry<Byte> eS = (Entry<Byte>) e;
return eS.value;
}
public static Entry mkDouble(String name, double value)
{
return new Entry<Double>(value, name);
}
public static double getDouble(Entry e)
{
Entry<Double> eS = (Entry<Double>) e;
return eS.value;
}
public static Entry mkFloat(String name, float value)
{
return new Entry<Float>(value, name);
}
public static float getFloat(Entry e)
{
Entry<Float> eS = (Entry<Float>) e;
return eS.value;
}
public static Entry mkIntArray(String name, int[] value)
{
return new Entry<int[]>(value, name);
}
public static int[] getIntArray(Entry e)
{
Entry<int[]> eS = (Entry<int[]>) e;
return eS.value;
}
public static Entry mkStringArray(String name, String[] value)
{
return new Entry<String[]>(value, name);
}
public static String[] getStringArray(Entry e)
{
Entry<String[]> eS = (Entry<String[]>) e;
return eS.value;
}
public static Entry mkByteArray(String name, byte[] value)
{
return new Entry<byte[]>(value, name);
}
public static byte[] getByteArray(Entry e)
{
Entry<byte[]> eS = (Entry<byte[]>) e;
return eS.value;
}
public static Entry mkUUID(String name, UUID ID)
{
long[] uid = new long[2];
uid[0] = ID.getLeastSignificantBits();
uid[1] = ID.getMostSignificantBits();
return new Entry<long[]>(uid, name);
}
public static UUID getUUID(Entry e)
{
Entry<long[]> uid = (Entry<long[]>) e;
return new UUID(uid.value[1], uid.value[0]);
}
}

View file

@ -0,0 +1,42 @@
package dev.zontreck.ariaslib.file;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Folder
{
public static void add(Entry e, Entry item)
{
((Entry<List<Entry>>)e).value.add(item);
}
public static void remove(Entry e, Entry item)
{
((Entry<List<Entry>>)e).value.remove(item);
}
public static Entry getEntry(Entry item, String name)
{
List<Entry> ret = ((Entry<List<Entry>>)item).value;
if(ret.size()>0)
{
for (Entry ent :
ret) {
if(ent.name.equals(name))return ent;
}
}
return null;
}
public static int size(Entry e)
{
return ((Entry<List<Entry>>)e).value.size();
}
public static Entry<List<Entry>> getNew(String name)
{
return new Entry<>(new ArrayList<Entry>(), name);
}
}

View file

@ -0,0 +1,283 @@
package dev.zontreck.ariaslib.html;
import dev.zontreck.ariaslib.html.bootstrap.Color;
import dev.zontreck.ariaslib.html.bootstrap.Icons;
import dev.zontreck.ariaslib.html.bootstrap.Size;
import dev.zontreck.ariaslib.util.Percent;
public class Bootstrap {
public static class Border {
public Side side;
public int width = 1;
public boolean usesSides = false;
public Colors colors;
public boolean invert;
public static Border make() {
return new Border();
}
public Border withColor(Colors color) {
this.colors = color.withPrefix("border");
return this;
}
public Border widthSide(Side side) {
this.side = side;
usesSides = true;
return this;
}
public Border withWidth(int width) {
this.width = width;
return this;
}
/**
* Removes borders instead of adding
*/
public Border setInverted() {
invert = true;
return this;
}
public void apply(HTMLElementBuilder elem) {
elem.addClass("border");
colors.apply(elem);
if (usesSides) {
elem.addClass("border-" + side.name().toLowerCase() + (invert ? "-0" : ""));
} else {
if (invert) elem.addClass("border-0");
}
}
public enum Side {
Start,
End,
Top,
Bottom
}
}
public static class Opacity {
public Percent value;
public String prefix;
public static Opacity make() {
return new Opacity();
}
public Opacity withPercent(Percent val) {
value = val;
return this;
}
public Opacity withPrefix(String pref) {
this.prefix = pref;
return this;
}
public void apply(HTMLElementBuilder builder) {
builder.addClass((prefix != "" ? prefix + "-" : "") + "opacity-" + value.get());
}
}
public static class Colors {
public Color color;
public boolean emphasis;
public boolean subtle;
public String prefix;
public static Colors make() {
return new Colors();
}
public Colors withColor(Color color) {
this.color = color;
return this;
}
public Colors setEmphasis() {
emphasis = true;
return this;
}
public Colors setSubtle() {
subtle = true;
return this;
}
public Colors withPrefix(String prefix) {
this.prefix = prefix;
return this;
}
public void apply(HTMLElementBuilder builder) {
builder.addClass(((prefix != "") ? prefix + "-" : "") + color.name().toLowerCase() + (emphasis ? "-emphasis" : "") + (subtle ? "-subtle" : ""));
}
}
public static class Background {
public Colors color;
public Opacity opacity;
public boolean gradient;
public static Background make() {
return new Background();
}
public Background withColor(Colors color) {
this.color = color.withPrefix("bg");
return this;
}
public Background withOpacity(Opacity op) {
this.opacity = op.withPrefix("bg");
return this;
}
public Background setGradient() {
gradient = true;
return this;
}
public void apply(HTMLElementBuilder builder) {
color.apply(builder);
opacity.apply(builder);
if (gradient)
builder.addClass(".bg-gradient");
}
}
public static class Shadow {
public Size size;
public static Shadow make() {
return new Shadow();
}
public Shadow withSize(Size size) {
this.size = size;
return this;
}
public void apply(HTMLElementBuilder builder) {
builder.addClass("shadow" + size.sizeText());
}
}
public static class FocusRing {
public Colors color;
public static FocusRing make() {
return new FocusRing();
}
public FocusRing withColor(Colors color) {
this.color = color.withPrefix("focus-ring");
return this;
}
public void apply(HTMLElementBuilder builder) {
builder.addClass("focus-ring");
color.apply(builder);
}
}
public static class Link {
public Colors color;
public static Link make() {
return new Link();
}
public Link withColor(Colors color) {
this.color = color.withPrefix("link");
return this;
}
public void apply(HTMLElementBuilder builder) {
color.apply(builder);
}
}
public static class Toast {
public Icons icon;
public HTMLElementBuilder toastHeader;
public HTMLElementBuilder toastBody;
public Toast() {
toastHeader = new HTMLElementBuilder("div").addClass("toast-header");
toastHeader.addChild("svg").addClass("bi").addClass(icon.getClassName()).addClass("rounded");
toastHeader.addChild("strong").addClass("me-auto");
toastHeader.addChild("small").withText("Text?");
toastHeader.addChild("button").withAttribute("type", "button").addClass("btn-close").withAttribute("data-bs-dismiss", "toast").withAttribute("aria-label", "Close");
toastBody = new HTMLElementBuilder("div").addClass("toast-body");
}
public static Toast make() {
return new Toast();
}
public Toast withIcon(Icons icon) {
this.icon = icon;
return this;
}
public void apply(HTMLElementBuilder builder) {
HTMLElementBuilder toast = builder.addChild("div").addClass("toast").withAttribute("role", "alert").withAttribute("aria-live", "assertive").withAttribute("aria-atomic", "true");
toast.addChild(toastHeader);
toast.addChild(toastBody);
}
}
public static class Button {
public Colors color;
public boolean outline;
public Size size;
public static Button make() {
return new Button();
}
public Button withColor(Colors color) {
this.color = color;
return this;
}
public Button setOutline() {
outline = true;
return this;
}
public Button withSize(Size size) {
this.size = size;
return this;
}
public void apply(HTMLElementBuilder builder) {
builder.addClass("btn");
if (outline) {
color.withPrefix("btn-outline");
} else color.withPrefix("btn");
color.apply(builder);
if (size != Size.Regular)
builder.addClass("btn" + size.sizeText());
}
}
public static class Disabled {
public static void setDisabled(HTMLElementBuilder builder) {
builder.withAttribute("disabled");
}
}
}

View file

@ -0,0 +1,8 @@
package dev.zontreck.ariaslib.html;
// Class attribute class for HTML element classes
class ClassAttribute extends HTMLAttribute {
public ClassAttribute(String value) {
super("class", value);
}
}

View file

@ -0,0 +1,55 @@
package dev.zontreck.ariaslib.html;
public class DOM {
public static HTMLElementBuilder beginBootstrapDOM(String pageTitle) {
HTMLElementBuilder builder = new HTMLElementBuilder("!doctype").withText("html");
HTMLElementBuilder html = builder.getOrCreate("html");
HTMLElementBuilder head = html.getOrCreate("head");
head.addChild("meta").withAttribute("charset", "utf-8");
head.addChild("meta").withAttribute("name", "viewport").withAttribute("content", "width=device-width, initial-scale=1");
head.getOrCreate("link").withAttribute("href", "https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css").withAttribute("integrity", "sha384-9ndCyUaIbzAi2FUVXJi0CjmCapSmO7SnpJef0486qhLnuZ2cdeRhO02iuK6FUUVM").withAttribute("crossorigin", "anonymous").withAttribute("rel", "stylesheet");
head.addClass("link").withAttribute("rel", "stylesheet").withAttribute("href", "https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.5/font/bootstrap-icons.css");
head.getOrCreate("title").withText(pageTitle);
HTMLElementBuilder body = html.getOrCreate("body");
body.addChild("script").withAttribute("src", "https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js").withAttribute("integrity", "sha384-geWF76RCwLtnZ8qwWowPQNguL3RmwHVBC9FhGdlKrxdiJJigb/j/68SIy3Te4Bkz").withAttribute("crossorigin", "anonymous").withText(" ");
body.addChild("script").withAttribute("src", "https://code.jquery.com/jquery-3.7.0.min.js").withAttribute("crossorigin", "anonymous").withText(" ");
body.addChild("style").withText("\n" +
" .command-popover{\n" +
" --bs-popover-header-bg: var(--bs-info);\n" +
" --bs-popover-header-color: var(--bs-dark);\n" +
" --bs-popover-bg: var(--bs-dark);\n" +
" --bs-popover-body-color: var(--bs-light);\n" +
" }\n");
return builder;
}
public static void addPopOverScan(HTMLElementBuilder builder) {
builder.getChildByTagName("html").getChildByTagName("body").addChild("script").withText("" +
"function scanPopOver()" +
"{" +
"var popoverTriggerList = document.querySelectorAll('[data-bs-toggle=\"popover\"]');\n" +
"var popoverList = [...popoverTriggerList].map(popoverTriggerEl => new bootstrap.Popover(popoverTriggerEl));" +
"" +
"}");
}
public static String closeHTML() {
return "</body></html>";
}
}

View file

@ -0,0 +1,24 @@
package dev.zontreck.ariaslib.html;
// Attribute class for HTML element attributes
class HTMLAttribute {
private String name;
private String value;
public HTMLAttribute(String name, String value) {
this.name = name;
this.value = value;
}
public HTMLAttribute(String name) {
this(name, null);
}
public String getName() {
return name;
}
public String getValue() {
return value;
}
}

View file

@ -0,0 +1,72 @@
package dev.zontreck.ariaslib.html;
import java.util.List;
// HTML element class supporting tag attributes
public class HTMLElement {
private String tagName;
private String text;
private List<HTMLAttribute> attributes;
private List<HTMLElement> children;
private boolean isEmptyElement;
public HTMLElement ( String tagName , String text , List<HTMLAttribute> attributes , List<HTMLElement> children , boolean isEmptyElement ) {
this.tagName = tagName;
this.text = text;
this.attributes = attributes;
this.children = children;
this.isEmptyElement = isEmptyElement;
}
public String getTagName ( ) {
return tagName;
}
public String generateHTML ( ) {
StringBuilder builder = new StringBuilder ( );
if ( "!doctype".equalsIgnoreCase ( tagName ) ) {
builder.append ( "<" ).append ( tagName ).append ( " " ).append ( text ).append ( ">\n" );
for ( HTMLElement child : children ) {
builder.append ( child.generateHTML ( ) );
}
return builder.toString ( );
}
builder.append ( "<" ).append ( tagName );
for ( HTMLAttribute attribute : attributes ) {
builder.append ( " " )
.append ( attribute.getName ( ) );
String value = attribute.getValue ( );
if ( value != null ) {
builder.append ( "=\"" ).append ( value ).append ( "\"" );
}
}
/*
if ( isEmptyElement ) {
builder.append ( " />\n" );
return builder.toString ( );
}*/
builder.append ( ">" );
if ( text != null ) {
builder.append ( text );
}
if ( ! isEmptyElement ) {
for ( HTMLElement child : children ) {
builder.append ( child.generateHTML ( ) );
}
}
builder.append ( "</" ).append ( tagName ).append ( ">\n" );
return builder.toString ( );
}
}

View file

@ -0,0 +1,118 @@
package dev.zontreck.ariaslib.html;
import java.util.ArrayList;
import java.util.List;
// Builder class for building HTML elements
public class HTMLElementBuilder {
private String tagName;
private String text;
private List<HTMLAttribute> attributes;
private List<HTMLElementBuilder> childElementBuilders;
public HTMLElementBuilder ( String tagName ) {
this.tagName = tagName;
this.attributes = new ArrayList<> ( );
this.childElementBuilders = new ArrayList<> ( );
}
public HTMLElementBuilder withText ( String text ) {
this.text = text;
return this;
}
public HTMLElementBuilder withAttribute ( String name , String value ) {
HTMLAttribute attribute = new HTMLAttribute ( name , value );
this.attributes.add ( attribute );
return this;
}
public HTMLElementBuilder withAttribute ( String name ) {
HTMLAttribute attribute = new HTMLAttribute ( name );
this.attributes.add ( attribute );
return this;
}
public HTMLElementBuilder addClass ( String className ) {
ClassAttribute classAttribute = getClassAttribute ( );
if ( classAttribute == null ) {
classAttribute = new ClassAttribute ( className );
this.attributes.add ( classAttribute );
}
else {
String existingValue = classAttribute.getValue ( );
classAttribute = new ClassAttribute ( existingValue + " " + className );
this.attributes.removeIf ( attr -> attr.getName ( ).equalsIgnoreCase ( "class" ) );
this.attributes.add ( classAttribute );
}
return this;
}
private ClassAttribute getClassAttribute ( ) {
for ( HTMLAttribute attribute : attributes ) {
if ( attribute instanceof ClassAttribute ) {
return ( ClassAttribute ) attribute;
}
}
return null;
}
public HTMLElementBuilder addChild ( HTMLElementBuilder childBuilder ) {
childElementBuilders.add ( childBuilder );
return this;
}
public HTMLElementBuilder addChild ( String tagName ) {
HTMLElementBuilder childBuilder = new HTMLElementBuilder ( tagName );
childElementBuilders.add ( childBuilder );
return childBuilder;
}
public HTMLElementBuilder getOrCreate ( String tagName ) {
HTMLElementBuilder childBuilder = getChildByTagName ( tagName );
if ( childBuilder == null ) {
childBuilder = addChild ( tagName );
}
return childBuilder;
}
public HTMLElementBuilder getChildByTagName ( String tagName ) {
return getChildByTagName ( tagName , 0 );
}
public HTMLElementBuilder getChildByTagName ( String tagName , int index ) {
List<HTMLElementBuilder> matchingChildBuilders = new ArrayList<> ( );
for ( HTMLElementBuilder builder : childElementBuilders ) {
if ( builder.tagName.equalsIgnoreCase ( tagName ) ) {
matchingChildBuilders.add ( builder );
}
}
if ( matchingChildBuilders.size ( ) > index ) {
return matchingChildBuilders.get ( index );
}
return null;
}
private boolean hasTextOrChildren ( ) {
return text != null || ! childElementBuilders.isEmpty ( );
}
public HTMLElement build ( ) {
List<HTMLElement> children = buildChildren ( );
boolean isEmptyElement = ! hasTextOrChildren ( );
return new HTMLElement ( tagName , text , attributes , children , isEmptyElement );
}
private List<HTMLElement> buildChildren ( ) {
List<HTMLElement> children = new ArrayList<> ( );
for ( HTMLElementBuilder builder : childElementBuilders ) {
children.add ( builder.build ( ) );
}
return children;
}
}

View file

@ -0,0 +1,46 @@
package dev.zontreck.ariaslib.html.bootstrap;
public enum Color
{
/**
* Dark Blue
*/
Primary,
/**
* Dark Gray
*/
Secondary,
/**
* Dark Green
*/
Success,
/**
* Dark Red
*/
Danger,
/**
* Yellow
*/
Warning,
/**
* Light Blue
*/
Info,
/**
* Black
*/
Dark,
/**
* Semi-gray
*/
Light,
Black,
White
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,25 @@
package dev.zontreck.ariaslib.html.bootstrap;
public enum Size {
Small,
Regular,
Large,
None;
public String sizeText() {
switch (this) {
case Small:
return "-sm";
case None:
return "-none";
case Large:
return "-lg";
default:
return "";
}
}
}

View file

@ -0,0 +1,9 @@
package dev.zontreck.ariaslib.http;
public enum HTTPMethod
{
GET,
POST,
PUT,
DELETE
}

View file

@ -0,0 +1,15 @@
package dev.zontreck.ariaslib.http;
public class HTTPRequest
{
public String url;
public String method;
public String body;
public String contentType;
protected HTTPRequest(){
}
}

View file

@ -0,0 +1,134 @@
package dev.zontreck.ariaslib.http;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
public class HTTPRequestBuilder
{
private HttpURLConnection connection;
private URL url;
private HTTPRequest request = new HTTPRequest();
public static HTTPRequestBuilder builder()
{
return new HTTPRequestBuilder();
}
protected HTTPRequestBuilder()
{
}
/**
* Sets the url in this request to the one supplied
* @param url The url to connect to
* @return Builder instance
* @throws MalformedURLException If the URL supplied was invalid
*/
public HTTPRequestBuilder withURL( String url) throws MalformedURLException {
request.url = url;
this.url = new URL(url);
return this;
}
/**
* Sets the HTTP Request method
* @param method The method you want to use
* @see HTTPMethod
* @return Builder instance
*/
public HTTPRequestBuilder withMethod(HTTPMethod method)
{
switch(method)
{
case GET:
{
request.method = "GET";
break;
}
case POST: {
request.method = "POST";
if(request.contentType.isEmpty()) request.contentType = "application/x-www-form-urlencoded";
break;
}
case DELETE:{
request.method = "DELETE";
break;
}
case PUT:{
request.method = "PUT";
if(request.contentType.isEmpty()) request.contentType = "application/x-www-form-urlencoded";
break;
}
}
return this;
}
/**
* Sets the request body. This may only be processed by the server when using POST or PUT, depending on the server's setup
* @param body The body to upload
* @return Builder Instance
*/
public HTTPRequestBuilder withBody(String body)
{
request.body = body;
return this;
}
/**
* Sets the content type header
* Default: application/x-www-form-urlencoded for POST/PUT, and null/not present for GET
* @param type
* @return
*/
public HTTPRequestBuilder withContentType(String type)
{
request.contentType = type;
return this;
}
public HTTPResponse build()
{
try {
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod(request.method);
byte[] array = request.body.getBytes("UTF-8");
connection.setRequestProperty("Content-Length" , "" + array.length);
connection.setRequestProperty("Content-Type", request.contentType);
connection.setDoInput(true);
connection.setUseCaches(false);
connection.setDoOutput(true);
DataOutputStream dos = new DataOutputStream(connection.getOutputStream());
dos.write(array);
dos.flush();
dos.close();
// Get the response body
InputStream inputStream = connection.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
StringBuilder response = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
response.append(line);
}
reader.close();
inputStream.close();
String responseBody = response.toString();
return new HTTPResponse(connection.getContentType(), connection.getResponseCode(), responseBody, request);
} catch (IOException e) {
throw new RuntimeException(e);
}finally {
connection.disconnect();
}
}
}

View file

@ -0,0 +1,33 @@
package dev.zontreck.ariaslib.http;
public class HTTPResponse
{
private String ContentType;
private int ResponseCode;
private String ResponseBody;
private HTTPRequest OriginalRequest;
protected HTTPResponse(String contentType, int code, String body, HTTPRequest request){
this.ContentType = contentType;
this.ResponseCode = code;
this.ResponseBody = body;
this.OriginalRequest = request;
}
public String getContentType() {
return ContentType;
}
public int getResponseCode() {
return ResponseCode;
}
public String getResponseBody() {
return ResponseBody;
}
public HTTPRequest getOriginalRequest() {
return OriginalRequest;
}
}

View file

@ -0,0 +1,15 @@
package dev.zontreck.ariaslib.json;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* Serialization or Deserialization has completed.
*
* The method takes 1 argument.
*
* Boolean: True for deserialization.
*/
@Retention ( RetentionPolicy.RUNTIME )
public @interface Completed {
}

View file

@ -0,0 +1,11 @@
package dev.zontreck.ariaslib.json;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* Used on a class to indicate that it is serializable by the dynamic serializer.
*/
@Retention ( RetentionPolicy.RUNTIME )
public @interface DynSerial {
}

View file

@ -0,0 +1,119 @@
package dev.zontreck.ariaslib.json;
import java.io.ByteArrayInputStream;
import java.lang.reflect.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Deserializes objects!
* <p>
* YOU MUST HAVE A NO-PARAMETER CONSTRUCTOR
*/
public class DynamicDeserializer {
/**
* Constructs and deserializes an object from serialized data
*/
public static <T> T doDeserialize ( Class<T> clazz , byte[] data ) throws Exception {
ByteArrayInputStream BAIS = new ByteArrayInputStream ( data );
return deserialize ( ( Map<String, Object> ) JsonObject.parseJSON ( BAIS ).getMap ( ) , clazz );
}
private static <T> T deserialize ( Map<String, Object> map , Class<T> clazz ) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
if ( ! clazz.isAnnotationPresent ( DynSerial.class ) )
return null;
T object = clazz.getDeclaredConstructor ( ).newInstance ( );
Field[] fields = clazz.getDeclaredFields ( );
for ( Field field : fields ) {
field.setAccessible ( true );
if ( field.isAnnotationPresent ( IgnoreSerialization.class ) )
continue;
try {
if ( List.class.isAssignableFrom ( field.getType ( ) ) ) {
Class<?> listType = getListType ( field );
List<Object> list = new ArrayList<> ( );
List<?> serializedList = ( List<?> ) map.get ( field.getName ( ) );
if ( serializedList != null ) {
for ( Object listItem : serializedList ) {
if ( listType.isAnnotationPresent ( DynSerial.class ) ) {
Object deserializedItem = deserialize ( ( Map<String, Object> ) listItem , listType );
list.add ( deserializedItem );
}
else {
list.add ( listItem );
}
}
}
field.set ( object , list );
}
else if ( Map.class.isAssignableFrom ( field.getType ( ) ) ) {
Class<?> valueType = getMapValueType ( field );
Map<String, Object> serializedMap = ( Map<String, Object> ) map.get ( field.getName ( ) );
if ( serializedMap != null ) {
Map<String, Object> mapValue = new HashMap<> ( );
for ( Map.Entry<String, Object> entry : serializedMap.entrySet ( ) ) {
Object deserializedValue;
if ( valueType.isAnnotationPresent ( DynSerial.class ) ) {
deserializedValue = deserialize ( ( Map<String, Object> ) entry.getValue ( ) , valueType );
}
else {
deserializedValue = entry.getValue ( );
}
mapValue.put ( entry.getKey ( ) , deserializedValue );
}
field.set ( object , mapValue );
}
}
else if ( ! field.getType ( ).isAnnotationPresent ( DynSerial.class ) ) {
field.set ( object , map.get ( field.getName ( ) ) );
}
else {
Object tmp = deserialize ( ( Map<String, Object> ) map.get ( field.getName ( ) ) , field.getType ( ) );
field.set ( object , tmp );
}
} catch ( Exception e ) {
// Handle any exceptions during deserialization
}
}
Method[] methods = clazz.getDeclaredMethods ( );
for ( Method method : methods ) {
if ( method.isAnnotationPresent ( Completed.class ) ) {
method.invoke ( object , true );
}
}
return object;
}
private static Class<?> getListType ( Field field ) {
Type genericType = field.getGenericType ( );
if ( genericType instanceof ParameterizedType ) {
ParameterizedType paramType = ( ParameterizedType ) genericType;
Type[] actualTypeArgs = paramType.getActualTypeArguments ( );
if ( actualTypeArgs.length > 0 ) {
return ( Class<?> ) actualTypeArgs[ 0 ];
}
}
return Object.class;
}
private static Class<?> getMapValueType ( Field field ) {
Type genericType = field.getGenericType ( );
if ( genericType instanceof ParameterizedType ) {
ParameterizedType paramType = ( ParameterizedType ) genericType;
Type[] actualTypeArgs = paramType.getActualTypeArguments ( );
if ( actualTypeArgs.length > 1 ) {
return ( Class<?> ) actualTypeArgs[ 1 ];
}
}
return Object.class;
}
}

View file

@ -0,0 +1,115 @@
package dev.zontreck.ariaslib.json;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class DynamicSerializer {
/**
* Serializes the object instance
*
* @param inst The class object to serialize
* @return A byte array of serialized data
*/
public static byte[] doSerialize(Object inst) throws InvocationTargetException, IllegalAccessException {
Map<String, Object> ret = serialize(inst);
JsonObject js = new JsonObject(ret);
return js.toJSONString().getBytes();
}
private static Map<String, Object> serialize(Object inst) throws InvocationTargetException, IllegalAccessException {
Class<?> clazz = inst.getClass();
if (!clazz.isAnnotationPresent(DynSerial.class))
return null;
Method[] mth = clazz.getDeclaredMethods();
Method onComplete = null;
for (
Method mt :
mth
) {
if (mt.isAnnotationPresent(PreSerialize.class)) {
mt.invoke(inst);
}
if (mt.isAnnotationPresent(Completed.class))
onComplete = mt;
}
Field[] fields = clazz.getDeclaredFields();
Map<String, Object> ret = new HashMap<>();
for (
Field field :
fields
) {
field.setAccessible(true);
if (field.isAnnotationPresent(IgnoreSerialization.class))
continue;
Object fieldVal = field.get(inst);
if (fieldVal == null) continue;
String fieldName = field.getName();
if (field.isAnnotationPresent(ListOrMap.class)) {
// Special handling for List and Map types
ret.put(fieldName, serializeCollectionOrMap(fieldVal));
continue;
}
if (!(fieldVal.getClass().isAnnotationPresent(DynSerial.class))) {
// Special handler for List and Map is needed right here.
if (fieldVal instanceof List || fieldVal instanceof Map) continue;
ret.put(fieldName, fieldVal);
} else {
Map<String, Object> TMP = serialize(fieldVal);
ret.put(fieldName, TMP);
}
}
if (onComplete != null)
onComplete.invoke(inst, false);
return ret;
}
@SuppressWarnings("unchecked")
private static Object serializeCollectionOrMap(Object collectionOrMap) throws InvocationTargetException, IllegalAccessException {
if (collectionOrMap instanceof List<?>) {
List<?> list = (List<?>) collectionOrMap;
List<Object> serializedList = new ArrayList<>();
for (Object item : list) {
if (item.getClass().isAnnotationPresent(DynSerial.class)) {
serializedList.add(serialize(item));
} else {
serializedList.add(item);
}
}
return serializedList;
} else if (collectionOrMap instanceof Map<?, ?>) {
Map<?, ?> mp = (Map<?, ?>) collectionOrMap;
Map<String, Object> map = (Map<String, Object>) mp;
Map<String, Object> serializedMap = new HashMap<>();
for (Map.Entry<String, Object> entry : map.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
if (value.getClass().isAnnotationPresent(DynSerial.class)) {
value = serialize(value);
}
serializedMap.put(key, value);
}
return serializedMap;
}
return collectionOrMap;
}
}

View file

@ -0,0 +1,12 @@
package dev.zontreck.ariaslib.json;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* Marks an element to be ignored completely by the serializer or deserializer.
*/
@Retention ( RetentionPolicy.RUNTIME )
public @interface IgnoreSerialization
{
}

View file

@ -0,0 +1,183 @@
package dev.zontreck.ariaslib.json;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class JsonObject {
private Map<String, Object> data;
public JsonObject() {
data = new HashMap<>();
}
public JsonObject(Map<String, Object> dat) {
data = new HashMap<>(dat);
}
public static JsonObject parseJSON(InputStream inputStream) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
StringBuilder jsonString = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
jsonString.append(line);
}
return parseJsonObject(jsonString.toString());
}
private static JsonObject parseJsonObject(String jsonString) {
JsonObject jsonObject = new JsonObject();
jsonString = jsonString.trim();
if (jsonString.startsWith("{") && jsonString.endsWith("}")) {
jsonString = jsonString.substring(1, jsonString.length() - 1);
String[] keyValuePairs = jsonString.split(",");
for (String pair : keyValuePairs) {
String[] keyValue = pair.split(":");
if (keyValue.length == 2) {
String key = keyValue[0].trim().replace("\"", "");
String value = keyValue[1].trim();
jsonObject.put(key, parseValue(value));
}
}
}
return jsonObject;
}
private static Object parseValue(String value) {
if (value.startsWith("{") && value.endsWith("}")) {
return parseJsonObject(value);
} else if (value.startsWith("[") && value.endsWith("]")) {
return parseJSONArray(value);
} else if (value.startsWith("\"") && value.endsWith("\"")) {
return value.substring(1, value.length() - 1);
} else if (value.equalsIgnoreCase("true")) {
return true;
} else if (value.equalsIgnoreCase("false")) {
return false;
} else if (value.equalsIgnoreCase("null")) {
return null;
} else {
try {
return Integer.parseInt(value);
} catch (NumberFormatException e) {
try {
return Double.parseDouble(value);
} catch (NumberFormatException ex) {
return value;
}
}
}
}
private static List<Object> parseJSONArray(String jsonArray) {
List<Object> list = new ArrayList<>();
jsonArray = jsonArray.trim();
if (jsonArray.startsWith("[") && jsonArray.endsWith("]")) {
jsonArray = jsonArray.substring(1, jsonArray.length() - 1);
String[] elements = jsonArray.split(",");
for (String element : elements) {
list.add(parseValue(element.trim()));
}
}
return list;
}
public void put(String key, Object value) {
data.put(key, value);
}
public Object get(String key) {
return data.get(key);
}
public void merge(Map<String, Object> ret) {
data.putAll(ret);
}
public Map<String, Object> getMap() {
return new HashMap<>(data);
}
public void add(String key, Object value) {
if (data.containsKey(key)) {
Object existingValue = data.get(key);
if (existingValue instanceof List) {
((List<Object>) existingValue).add(value);
} else {
List<Object> list = new ArrayList<>();
list.add(existingValue);
list.add(value);
data.put(key, list);
}
} else {
data.put(key, value);
}
}
public String toJSONString() {
StringBuilder sb = new StringBuilder();
sb.append("{");
boolean first = true;
for (Map.Entry<String, Object> entry : data.entrySet()) {
if (!first) {
sb.append(",");
}
first = false;
sb.append("\"");
sb.append(escape(entry.getKey()));
sb.append("\":");
sb.append(toJSONValue(entry.getValue()));
}
sb.append("}");
return sb.toString();
}
private String escape(String str) {
if (str == null) return "";
// Add necessary escape characters (e.g., double quotes, backslashes)
// You can implement this method based on your specific requirements.
// This is a simplified version for demonstration purposes.
return str.replace("\"", "\\\"");
}
private String toJSONValue(Object value) {
if (value instanceof String) {
return "\"" + escape(value.toString()) + "\"";
} else if (value instanceof JsonObject) {
return ((JsonObject) value).toJSONString();
} else if (value instanceof List) {
return toJSONList((List<Object>) value);
} else if (value instanceof Map<?, ?>) {
return new JsonObject((Map<String, Object>) ((Map<?, ?>) value)).toJSONString();
} else {
return value.toString();
}
}
private String toJSONList(List<Object> list) {
StringBuilder sb = new StringBuilder();
sb.append("[");
boolean first = true;
for (Object item : list) {
if (!first) {
sb.append(",");
}
first = false;
sb.append(toJSONValue(item));
}
sb.append("]");
return sb.toString();
}
}

View file

@ -0,0 +1,8 @@
package dev.zontreck.ariaslib.json;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention ( RetentionPolicy.RUNTIME )
public @interface ListOrMap {
}

View file

@ -0,0 +1,13 @@
package dev.zontreck.ariaslib.json;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* To be set on a method, and will invoke that method prior to serialization beginning.
*
* Preparations should be made here
*/
@Retention ( RetentionPolicy.RUNTIME )
public @interface PreSerialize {
}

View file

@ -0,0 +1,47 @@
package dev.zontreck.ariaslib.terminal;
import java.util.ArrayList;
import java.util.List;
public class Banners
{
public static String generateBanner(String text) {
int maxLength = calculateMaxLength(text);
List<String> bannerLines = new ArrayList<>();
StringBuilder border = new StringBuilder();
for (int i = 0; i < maxLength + 4; i++) {
border.append("*");
}
bannerLines.add(border.toString());
bannerLines.add("* " + centerText(text, maxLength) + " *");
bannerLines.add(border.toString());
return String.join("\n", bannerLines);
}
private static String centerText(String text, int maxLength) {
StringBuilder centeredText = new StringBuilder();
int spacesToAdd = (maxLength - text.length()) / 2;
for (int i = 0; i < spacesToAdd; i++) {
centeredText.append(" ");
}
centeredText.append(text);
for (int i = 0; i < spacesToAdd; i++) {
centeredText.append(" ");
}
if (centeredText.length() < maxLength) {
centeredText.append(" ");
}
return centeredText.toString();
}
private static int calculateMaxLength(String text) {
int maxLength = 0;
for (String line : text.split("\n")) {
if (line.length() > maxLength) {
maxLength = line.length();
}
}
return maxLength;
}
}

View file

@ -0,0 +1,88 @@
package dev.zontreck.ariaslib.terminal;
import dev.zontreck.ariaslib.util.DelayedExecutorService;
import dev.zontreck.ariaslib.util.EnvironmentUtils;
import dev.zontreck.ariaslib.util.Progress;
import java.util.TimerTask;
public abstract class Task extends TimerTask implements Runnable {
public final String TASK_NAME;
private TaskCompletionToken token = new TaskCompletionToken ( );
public static final String CHECK = "P";
public static final String FAIL = "F";
// Else use the progress spinner from the Progress class
private boolean isSilent = false;
public Task ( String name ) {
TASK_NAME = name;
}
/**
* This constructor is meant to be used to create silent tasks that do not output to the console. (Example usage: DelayedExecutionService)
*
* @param name Task name
* @param silent Whether to print to the terminal
*/
public Task ( String name , boolean silent ) {
this ( name );
isSilent = silent;
}
public boolean isComplete ( ) {
return token.get ( );
}
public void startTask ( ) {
Thread tx = new Thread(this);
tx.start();
if(! isSilent && !EnvironmentUtils.isRunningInsideDocker())
{
Thread tx2 = new Thread(new SpinnerTask(token, this));
tx2.start();
}
}
public void stopTask ( ) {
if ( token.get ( ) && ! isSilent ) {
System.out.printf ( "\r" + TASK_NAME + "\t\t[" + token.status + "]\n" );
}
}
public void setSuccess ( ) {
token.completed ( CHECK );
}
public void setFail ( ) {
token.completed ( FAIL );
}
public class SpinnerTask extends Task {
public final Task task;
public final TaskCompletionToken token;
private final Progress spinner = new Progress ( 100 );
public SpinnerTask ( TaskCompletionToken token , Task parent ) {
super ( "spinner" , true );
this.token = token;
this.task = parent;
}
@Override
public void run ( ) {
while ( ! task.isComplete ( ) ) {
try {
Thread.sleep ( 50L );
if ( ! task.isSilent && ! task.isComplete ( ) && ! EnvironmentUtils.isRunningInsideDocker ( ) )
System.out.printf ( "\r" + task.TASK_NAME + "\t\t" + spinner.getSpinnerTick ( ) + "\r" );
} catch ( Exception e ) {
e.printStackTrace ( );
}
}
}
}
}

View file

@ -0,0 +1,20 @@
package dev.zontreck.ariaslib.terminal;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* Should not be re-used for multiple tasks!!!
*/
public class TaskCompletionToken
{
private AtomicBoolean complete = new AtomicBoolean(false);
public String status = "";
public void completed(String reason){
status=reason;
complete.set(true);
}
public boolean get(){
return complete.get();
}
}

View file

@ -0,0 +1,35 @@
package dev.zontreck.ariaslib.terminal;
import dev.zontreck.ariaslib.util.EnvironmentUtils;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
public class Terminal {
private static final AtomicInteger ID = new AtomicInteger ( 0 );
private static final AtomicBoolean running = new AtomicBoolean ( true );
public static String PREFIX = "";
/**
* This starts a terminal instance
*
* @return The terminal ID
*/
public static int startTerminal ( ) {
if ( EnvironmentUtils.isRunningInsideDocker ( ) )
return 0;
running.set ( true );
//DelayedExecutorService.getInstance ( ).schedule ( new ConsolePrompt ( ) , 1 );
return ID.getAndIncrement ( );
}
public static boolean isRunning ( ) {
return running.get ( );
}
public static void setRunning ( boolean running ) {
Terminal.running.set ( running );
}
}

View file

@ -0,0 +1,17 @@
package dev.zontreck.ariaslib.util;
import java.time.Instant;
import java.util.*;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import dev.zontreck.ariaslib.terminal.Task;
import dev.zontreck.ariaslib.terminal.Terminal;
@Deprecated
public class DelayedExecutorService {
}

View file

@ -0,0 +1,19 @@
package dev.zontreck.ariaslib.util;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.stream.Stream;
public class EnvironmentUtils {
public static boolean isRunningInsideDocker ( ) {
if ( Files.exists ( Paths.get ( "/.dockerenv" ) ) )
return true;
try {
Stream<String> str = Files.lines ( Paths.get ( "/proc/1/cgroup" ) );
return str.anyMatch ( ln -> ln.contains ( "/docker" ) );
} catch ( IOException e ) {
return false;
}
}
}

View file

@ -0,0 +1,51 @@
package dev.zontreck.ariaslib.util;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
public class FileIO
{
public static String readFile(String filePath) {
try {
byte[] fileBytes = Files.readAllBytes(Paths.get(filePath));
return new String(fileBytes);
} catch (IOException e) {
return "An error occurred: " + e.getMessage();
}
}
public static void writeFile(String filePath, String newContent) {
try {
Files.write(Paths.get(filePath), newContent.getBytes());
} catch (IOException e) {
}
}
/**
* Recursively delete a directory
* @param directory The folder to delete
*/
public static void deleteDirectory(File directory) {
if (directory.exists()) {
File[] files = directory.listFiles();
if (files != null) {
for (File file : files) {
if (file.isDirectory()) {
deleteDirectory(file);
} else {
file.delete();
}
}
}
// Now directory is empty, so delete it
directory.delete();
System.out.println("Directory deleted: " + directory.getAbsolutePath());
} else {
System.out.println("Directory does not exist: " + directory.getAbsolutePath());
}
}
}

View file

@ -0,0 +1,120 @@
package dev.zontreck.ariaslib.util;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class Hashing
{
/**
* A md5 hashing function that is compatible with literally every other hashing function out there
* @param input The string to hash
* @return The hash
*/
public static String md5(String input) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(input.getBytes());
byte[] byteData = md.digest();
// Convert the byte array to a hexadecimal string
StringBuilder hexString = new StringBuilder();
for (byte aByteData : byteData) {
String hex = Integer.toHexString(0xff & aByteData);
if (hex.length() == 1) {
hexString.append('0');
}
hexString.append(hex);
}
return hexString.toString();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
return null;
}
}
/**
* A md5 hashing function that is compatible with literally every other hashing function out there
* @param input The bytes to hash
* @return The hash
*/
public static String md5(byte[] input) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(input);
byte[] byteData = md.digest();
// Convert the byte array to a hexadecimal string
StringBuilder hexString = new StringBuilder();
for (byte aByteData : byteData) {
String hex = Integer.toHexString(0xff & aByteData);
if (hex.length() == 1) {
hexString.append('0');
}
hexString.append(hex);
}
return hexString.toString();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
return null;
}
}
/**
* A sha256 hashing function that is compatible with literally every other hashing function out there
* @param input The string to hash
* @return The hash
*/
public static String sha256(String input) {
try {
MessageDigest md = MessageDigest.getInstance("SHA256");
md.update(input.getBytes());
byte[] byteData = md.digest();
// Convert the byte array to a hexadecimal string
StringBuilder hexString = new StringBuilder();
for (byte aByteData : byteData) {
String hex = Integer.toHexString(0xff & aByteData);
if (hex.length() == 1) {
hexString.append('0');
}
hexString.append(hex);
}
return hexString.toString();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
return null;
}
}
/**
* A sha256 hashing function that is compatible with literally every other hashing function out there
* @param input The bytes to hash
* @return The hash
*/
public static String sha256(byte[] input) {
try {
MessageDigest md = MessageDigest.getInstance("SHA256");
md.update(input);
byte[] byteData = md.digest();
// Convert the byte array to a hexadecimal string
StringBuilder hexString = new StringBuilder();
for (byte aByteData : byteData) {
String hex = Integer.toHexString(0xff & aByteData);
if (hex.length() == 1) {
hexString.append('0');
}
hexString.append(hex);
}
return hexString.toString();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
return null;
}
}
}

View file

@ -0,0 +1,94 @@
package dev.zontreck.ariaslib.util;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Lists
{
/**
* Programatically constructs a list
* @param values The list of values
* @return The new list
* @param <T> An arbitrary type parameter
*/
public static <T> List<T> of(T... values)
{
List<T> arr = new ArrayList<>();
for(T value : values)
{
arr.add(value);
}
return arr;
}
/**
* Splits a string into a list
* @param input The string to split
* @param delimiters The list of delimiters
* @return A non-strided list
*/
public static List<String> split(String input, String... delimiters) {
List<String> result = new ArrayList<>();
StringBuilder regex = new StringBuilder("(");
// Constructing the regular expression pattern with provided delimiters
for (String delimiter : delimiters) {
regex.append(delimiter).append("|");
}
regex.deleteCharAt(regex.length() - 1); // Remove the extra '|' character
regex.append(")");
String[] tokens = input.split(regex.toString());
// Add non-empty tokens to the result list
for (String token : tokens) {
if (!token.isEmpty()) {
result.add(token);
}
}
return result;
}
/**
* Split a string, and keep the delimiters
* @param input The string to be parsed and split
* @param delimiters A list of delimiters
* @return A strided list containing the parsed options, and the delimiters
*/
public static List<String> splitWithDelim(String input, String... delimiters) {
List<String> result = new ArrayList<>();
StringBuilder regex = new StringBuilder("(");
// Constructing the regular expression pattern with provided delimiters
for (String delimiter : delimiters) {
regex.append(delimiter).append("|");
}
regex.deleteCharAt(regex.length() - 1); // Remove the extra '|' character
regex.append(")");
// Splitting the input string using the regex pattern
String[] tokens = input.split(regex.toString());
// Adding tokens and delimiters to the result list in a strided manner
for (int i = 0; i < tokens.length; i++) {
if (!tokens[i].isEmpty()) {
result.add(tokens[i]);
}
// Adding delimiter if it exists and it's not the last token
if (i < tokens.length - 1) {
result.add(input.substring(input.indexOf(tokens[i]) + tokens[i].length(), input.indexOf(tokens[i + 1])));
}
}
return result;
}
private Lists(){
}
}

View file

@ -0,0 +1,49 @@
package dev.zontreck.ariaslib.util;
import java.util.HashMap;
import java.util.Map;
/**
* Utility class to assist in creating a dictionary programmatically in one line of code.
*/
public class Maps
{
/**
* This takes a list of entries and returns a HashMap
* @param entries The entries you want in your hashmap
* @return The map itself
* @param <A> Any typed parameter
* @param <B> Any typed parameter
*/
public static <A,B> Map<A,B> of(Entry<A,B>... entries) {
Map<A,B> map = new HashMap<>();
for(Entry<A,B> E : entries)
{
map.put(E.key, E.value);
}
return map;
}
/**
* A virtual entry used only by the Maps#of function.
* @see Maps#of(Entry[])
* @param <A> Any typed parameter
* @param <B> Any typed parameter
*/
public static class Entry<A,B> {
public final A key;
public final B value;
/**
* Initializes the readonly entry
* @param a The dictionary key
* @param b The value
*/
public Entry(A a, B b)
{
this.key=a;
this.value=b;
}
}
}

View file

@ -0,0 +1,18 @@
package dev.zontreck.ariaslib.util;
/**
* This class will be used to house math helper functions
*/
public class MathUtil
{
/**
* A newer helper function to get the percentage with large number support
* @param current Min value
* @param max Maximum value for progress
* @return Percentage
*/
public static int getPercent(long current, long max)
{
return Math.round(current*100/max);
}
}

View file

@ -0,0 +1,23 @@
package dev.zontreck.ariaslib.util;
import java.io.PrintStream;
public class Percent
{
int current;
int maximum;
public Percent(int cur, int max)
{
current=cur;
maximum=max;
}
public int get()
{
return ((current * 100) / maximum);
}
}

View file

@ -0,0 +1,56 @@
package dev.zontreck.ariaslib.util;
import java.util.concurrent.atomic.AtomicInteger;
public class Progress
{
private int maximum;
private int current;
private AtomicInteger tickNum = new AtomicInteger(0);
private static final String TICKS="-\\|/";
public String getSpinnerTick()
{
if(tickNum.get()>=TICKS.length()) tickNum.set(0);
return "[" + TICKS.substring(tickNum.getAndIncrement(), tickNum.get()) + "]";
}
public Progress(int maximum)
{
current=0;
this.maximum=maximum;
}
public int getPercent(){
return (current*100/maximum);
}
public String getPercentStr()
{
return (getPercent()+"%");
}
public static int getPercentOf(int current, int max)
{
return (current*100/max);
}
public void increment(){
current++;
sanity();
}
private void sanity(){
if(current > maximum) current = maximum;
if(current < 0)current = 0;
}
public void decrement(){
current--;
sanity();
}
public void setCurrent(int cur)
{
current=cur;
}
}

View file

@ -0,0 +1,66 @@
package dev.zontreck.ariaslib.util;
import java.io.PrintStream;
/**
* Utility to create an ascii progress bar
*/
public class ProgressBar
{
private static final int DEFAULT_BAR_WIDTH = 50;
/**
* Reserved spaces for the brackets, and the carrot, and the percent value.
*/
private static final int PROGRESS_BAR_RESERVED=5;
/**
* Always will return 80
* @return 80
*/
private static int getConsoleWidth() {
return 80; // Default console width, can be adjusted for different consoles
}
/**
* Build a progress bar
* <br><br>
* your text here [========= ] 40% your text here
* @param percent The percentage
* @param beforeText
* @param afterText
* @return ProgressBar as a String
*/
public static String printProgressBar(int percent, String beforeText, String afterText) {
StringBuilder sb = new StringBuilder();
int consoleWidth = getConsoleWidth();
int barWidth = Math.min(consoleWidth - beforeText.length() - afterText.length() - PROGRESS_BAR_RESERVED, DEFAULT_BAR_WIDTH);
// Calculate progress
int progressBarLength = (int) ((double) percent / 100 * barWidth);
// Print before text
sb.append(beforeText);
// Print progress bar
sb.append("[");
for (int i = 0; i < barWidth; i++) {
if (i < progressBarLength) {
sb.append("=");
}else if(i==progressBarLength) sb.append(">");
else {
sb.append(" ");
}
}
sb.append("]");
// Print percentage
sb.append(" " + percent + "%");
// Print after text
sb.append(afterText);
return sb.toString();
}
}

View file

@ -0,0 +1,161 @@
package dev.zontreck.ariaslib.util;
import java.util.List;
/**
* Contains useful structures and functions for dealing with, and manipulation of, time.
*/
public class TimeNotation
{
public int Years;
public int Months;
public int Weeks;
public int Days;
public int Hours;
public int Minutes;
public int Seconds;
public TimeNotation(int years, int months, int weeks, int days, int hours, int minutes, int seconds)
{
Years=years;
Months=months;
Weeks=weeks;
Days=days;
Hours=hours;
Minutes=minutes;
Seconds = seconds;
}
private TimeNotation(){}
@Override
public String toString() {
String str =
someOrNone(Years,Pluralize(Years, "year") + ", ") +
someOrNone(Months, Pluralize(Months, "month") + ", ") +
someOrNone(Weeks, Pluralize(Weeks, "week") + ", ") +
someOrNone(Days, Pluralize(Days, "day") + ", ") +
someOrNone(Hours, Pluralize(Hours, "hour") + ", ") +
someOrNone(Minutes, Pluralize(Minutes, "minute") + ", ") +
someOrNone(Seconds, Pluralize(Seconds, "second"));
if(str == ""){
return "No Seconds";
} else return str;
}
/**
* Create a plural version for a number
* @param num The number to prefix
* @param str The singular form of the string
* @return Combined string, num + str in plural form if necessary
*/
private String Pluralize(int num, String str)
{
return num + " " + ((num > 1) ? str+"s" : str);
}
/**
* A simple function to test a number, return a string, or return nothing at all.
* @param num The number to check
* @param str The string to return if the number is greater than zero
* @return Str if num >1, or empty string
*/
private String someOrNone(int num, String str)
{
if(num > 0) return str;
else return "";
}
/**
* A simple function to test a number, return a string, or return something else.
* @param num The number to check
* @param str The string to return if the number is greater than zero
* @return Str if num >1, or other string
*/
private String someOrOther(int num, String str, String other)
{
if(num > 0) return str;
else return other;
}
/**
* Encodes time notation!
* @return A program readable string that can be decoded back to a time notation
*/
public String toNotation()
{
return Years + "Y" + Months + "M" + Weeks + "W" + Days + "d" + Hours + "h" + Minutes + "m" + Seconds + "s";
}
/**
* Parses a time notation string
* @param notation Serialized time notation
* @return The deserialized time notation object
*/
public static TimeNotation fromNotation(String notation)
{
TimeNotation notationX = new TimeNotation();
String[] delims = new String[]{"Y", "M", "W", "d", "h", "m", "s"};
List<String> opts = Lists.split(notation, delims);
int index = 0;
for(String dlim : delims)
{
if(notation.contains(dlim))
{
switch (dlim)
{
case "Y":
{
notationX.Years = Integer.parseInt(opts.get(index));
break;
}
case "M":
{
notationX.Months = Integer.parseInt(opts.get(index));
break;
}
case "W":
{
notationX.Weeks = Integer.parseInt(opts.get(index));
break;
}
case "d":
{
notationX.Days = Integer.parseInt(opts.get(index));
break;
}
case "h":
{
notationX.Hours = Integer.parseInt(opts.get(index));
break;
}
case "m":
{
notationX.Minutes = Integer.parseInt(opts.get(index));
break;
}
case "s":
{
notationX.Seconds = Integer.parseInt(opts.get(index));
break;
}
}
index++;
}
}
return notationX;
}
}

View file

@ -0,0 +1,96 @@
package dev.zontreck.ariaslib.util;
/**
* This class is a helper with some minecraft specific functions
*/
public class TimeUtil
{
/**
* Converts seconds to ticks. (seconds*ticks)
* @param seconds Number of seconds
* @param ticks Number of ticks in a single second
* @return Number of ticks
*/
public static int secondsToTicks(int seconds, int ticks)
{
return seconds*ticks;
}
/**
* Converts the number of ticks to seconds
* @param ticks The number of ticks to convert
* @param ticksInASecond The number of ticks in a single second
* @return Number of seconds
*/
public static int ticksToSeconds(int ticks, int ticksInASecond)
{
return ticks / ticksInASecond;
}
/**
* Encodes a LibAC Time Notation
* @param seconds Number of seconds to convert
* @return Time Notation
*/
public static TimeNotation secondsToTimeNotation(int seconds)
{
int years = seconds / YEAR;
if(years > 0) seconds -= YEAR * years;
int month = seconds / MONTH;
if(month > 0) seconds -= MONTH * month;
int week = seconds / WEEK;
if(week > 0) seconds -= WEEK * week;
int day = seconds / DAY;
if(day > 0) seconds -= DAY * day;
int hour = seconds / HOUR;
if(hour > 0) seconds -= HOUR * hour;
int minute = seconds / MINUTE;
if(minute > 0) seconds -= MINUTE * minute;
return new TimeNotation(years, month, week, day, hour, minute, seconds);
}
/**
* Convert a time notation to seconds
* @param notation Notation to convert
* @return Total seconds
*/
public static int notationToSeconds(TimeNotation notation)
{
int seconds = 0;
seconds += (notation.Years * YEAR);
seconds += (notation.Months * MONTH);
seconds += (notation.Weeks * WEEK);
seconds += (notation.Days * DAY);
seconds += (notation.Hours * HOUR);
seconds += (notation.Minutes * MINUTE);
seconds += (notation.Seconds);
return seconds;
}
public static final int SECOND;
public static final int MINUTE;
public static final int HOUR;
public static final int DAY;
public static final int WEEK;
public static final int MONTH;
public static final int YEAR;
static {
SECOND = 1;
MINUTE = SECOND * 60;
HOUR = MINUTE * 60;
DAY = HOUR*24;
WEEK = DAY*7;
MONTH = WEEK*4;
YEAR = DAY*365;
}
}

View file

@ -0,0 +1,32 @@
package dev.zontreck.ariaslib.xmlrpc;
import java.util.Map;
public class MethodCall {
private String methodName;
private Object[] params;
public Map<String, Object> parameters;
public MethodCall ( String methodName , Object[] params , Map<String, Object> p ) {
this.methodName = methodName;
this.params = params;
this.parameters = p;
}
public String getMethodName ( ) {
return methodName;
}
public Object[] getParams ( ) {
return params;
}
public static MethodCall fromDeserializer ( XmlRpcDeserializer deserializer ) throws Exception {
String methodName = deserializer.readMethodName ( );
Object[] params = deserializer.readMethodParams ( );
Map<String, Object> parameters = ( Map<String, Object> ) params[ 0 ];
return new MethodCall ( methodName , params , parameters );
}
}

View file

@ -0,0 +1,26 @@
package dev.zontreck.ariaslib.xmlrpc;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
public class MethodResponse {
public Map<String, Object> parameters = new HashMap<> ( );
public MethodResponse ( ) {
}
public String toXml ( ) {
ByteArrayOutputStream baos = new ByteArrayOutputStream ( );
XmlRpcStreamWriter streamWriter = new XmlRpcStreamWriter ( baos );
try {
streamWriter.writeMethodResponse ( parameters );
return new String ( baos.toByteArray ( ) );
} catch ( IOException e ) {
throw new RuntimeException ( e );
}
}
}

View file

@ -0,0 +1,7 @@
XMLRPC
======
-----------
This code is heavily auto-generated from ChatGPT, however, it contains a lot of modifications to make it actually work.

View file

@ -0,0 +1,44 @@
package dev.zontreck.ariaslib.xmlrpc;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
public class XmlRpcDeserializer {
private XmlRpcStreamReader xmlStreamReader;
public XmlRpcDeserializer ( InputStream inputStream ) throws Exception {
xmlStreamReader = new XmlRpcStreamReader ( inputStream );
}
public String skipXmlHeader(String xml) {
int startIndex = xml.indexOf("<?xml");
if (startIndex >= 0) {
int endIndex = xml.indexOf("?>", startIndex);
if (endIndex >= 0) {
return xml.substring(endIndex + 2);
}
}
return xml;
}
public XmlRpcDeserializer ( String xml ) throws Exception {
byte[] xmlBytes = xml.getBytes ( );
ByteArrayInputStream inputStream = new ByteArrayInputStream ( xmlBytes );
xmlStreamReader = new XmlRpcStreamReader ( inputStream );
}
public String readMethodName ( ) throws Exception {
return xmlStreamReader.readMethodCallMethodName ( );
}
public Object[] readMethodParams ( ) throws Exception {
return xmlStreamReader.readMethodCallParams ( );
}
public Object readMethodResponse ( ) throws Exception {
return xmlStreamReader.readMethodResponseResult ( );
}
public void close ( ) throws Exception {
xmlStreamReader.close ( );
}
}

View file

@ -0,0 +1,24 @@
package dev.zontreck.ariaslib.xmlrpc;
public class XmlRpcException extends Exception {
public XmlRpcException ( int code , String message ) {
super ( message );
FaultCode = code;
FaultString = message;
}
public final String FaultString;
public final int FaultCode;
@Override
public String toString ( ) {
StringBuilder sb = new StringBuilder ( );
sb.append ( "Code: " +FaultCode);
sb.append ( "\nMessage: " +FaultString);
sb.append ( "\n\n" );
return sb.toString ();
}
}

View file

@ -0,0 +1,26 @@
package dev.zontreck.ariaslib.xmlrpc;
import java.io.IOException;
import java.io.OutputStream;
import java.util.List;
public class XmlRpcSerializer {
private XmlRpcStreamWriter writer;
public XmlRpcSerializer ( OutputStream outputStream ) {
this.writer = new XmlRpcStreamWriter ( outputStream );
}
public void serializeMethodCall ( String methodName , List<Object> params ) throws IOException {
writer.writeMethodCall ( methodName , params );
}
public void serializeMethodResponse ( Object value ) throws IOException {
writer.writeMethodResponse ( value );
}
public void close ( ) throws IOException {
writer.close ( );
}
}

View file

@ -0,0 +1,206 @@
package dev.zontreck.ariaslib.xmlrpc;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class XmlRpcStreamReader {
private XMLStreamReader xmlStreamReader;
public XmlRpcStreamReader ( InputStream inputStream ) throws XMLStreamException {
XMLInputFactory inputFactory = XMLInputFactory.newInstance ( );
xmlStreamReader = inputFactory.createXMLStreamReader ( inputStream );
}
private String CURRENT_TAG_NAME;
private int ELEM_TYPE;
public boolean nextTag ( ) throws XMLStreamException {
while ( xmlStreamReader.hasNext ( ) ) {
int eventType = xmlStreamReader.next ( );
if ( eventType == XMLStreamConstants.START_ELEMENT || eventType == XMLStreamConstants.END_ELEMENT ) {
CURRENT_TAG_NAME = getLocalName ( );
ELEM_TYPE = xmlStreamReader.getEventType ( );
return true;
}
}
return false;
}
public String getLocalName ( ) {
return xmlStreamReader.getLocalName ( );
}
public String getElementText ( ) throws XMLStreamException {
return xmlStreamReader.getElementText ( );
}
public void require ( int type , String namespaceURI , String localName ) throws XMLStreamException {
xmlStreamReader.require ( type , namespaceURI , localName );
}
public String readMethodCallMethodName ( ) throws XMLStreamException {
nextTag ( );
require ( XMLStreamConstants.START_ELEMENT , null , "methodCall" );
nextTag ( );
require ( XMLStreamConstants.START_ELEMENT , null , "methodName" );
return getElementText ( );
}
public Object[] readMethodCallParams ( ) throws XMLStreamException {
nextTag ( );
require ( XMLStreamConstants.START_ELEMENT , null , "params" );
return deserializeParams ( );
}
private Object[] deserializeParams ( ) throws XMLStreamException {
List<Object> paramsList = new ArrayList<> ( );
while ( xmlStreamReader.hasNext ( ) ) {
int event = xmlStreamReader.next ( );
if ( event == XMLStreamConstants.START_ELEMENT ) {
String elementName = xmlStreamReader.getLocalName ( );
if ( elementName.equals ( "param" ) ) {
nextTag ( );
require ( XMLStreamConstants.START_ELEMENT , null , "value" );
Object value = deserializeValue ( );
paramsList.add ( value );
}
}
}
return paramsList.toArray ( );
}
public Object readMethodResponseResult ( ) throws XMLStreamException {
nextTag ( );
require ( XMLStreamConstants.START_ELEMENT , null , "methodResponse" );
nextTag ( );
require ( XMLStreamConstants.START_ELEMENT , null , "params" );
nextTag ( );
require ( XMLStreamConstants.START_ELEMENT , null , "param" );
return deserializeValue ( );
}
private Object deserializeValue ( ) throws XMLStreamException {
nextTag ( );
int eventType = xmlStreamReader.getEventType ( );
if ( eventType == XMLStreamConstants.CHARACTERS || eventType == XMLStreamConstants.CDATA ) {
return xmlStreamReader.getText ( );
}
else if ( eventType == XMLStreamConstants.START_ELEMENT ) {
String localName = xmlStreamReader.getLocalName ( );
switch ( localName ) {
case "string":
return deserializeString ( );
case "i4":
case "int":
return deserializeInt ( );
case "double":
return deserializeDouble ( );
case "boolean":
return deserializeBoolean ( );
case "array":
return deserializeArray ( );
case "struct":
return deserializeStruct ( );
case "nil":
return null;
case "i8":
return deserializeLong ( );
default:
throw new IllegalArgumentException ( "Unsupported element: " + localName );
}
}
else {
throw new IllegalArgumentException ( "Unexpected event type: " + eventType );
}
}
private String deserializeString ( ) throws XMLStreamException {
return getElementText ( );
}
private int deserializeInt ( ) throws XMLStreamException {
return Integer.parseInt ( getElementText ( ) );
}
private byte deserializeByte ( ) throws XMLStreamException {
return Byte.parseByte ( getElementText ( ) );
}
private long deserializeLong ( ) throws XMLStreamException {
return Long.parseLong ( getElementText ( ) );
}
private double deserializeDouble ( ) throws XMLStreamException {
return Double.parseDouble ( getElementText ( ) );
}
private boolean deserializeBoolean ( ) throws XMLStreamException {
return Boolean.parseBoolean ( getElementText ( ) );
}
private Object[] deserializeArray ( ) throws XMLStreamException {
List<Object> arr = new ArrayList<> ( );
while ( nextTag ( ) ) {
if ( CURRENT_TAG_NAME.equals ( "data" ) && ELEM_TYPE == XMLStreamConstants.END_ELEMENT ) {
break;
}
else if ( CURRENT_TAG_NAME.equals ( "value" ) && ELEM_TYPE == XMLStreamConstants.START_ELEMENT ) {
arr.add ( deserializeValue ( ) );
}
}
return arr.toArray ( );
}
private Map<String, Object> deserializeStruct ( ) throws XMLStreamException {
Map<String, Object> struct = new HashMap<> ( );
String name = null;
while ( nextTag ( ) ) {
if ( xmlStreamReader.getLocalName ( ).equals ( "member" ) ) {
name = null;
}
else if ( xmlStreamReader.getLocalName ( ).equals ( "name" ) ) {
name = getElementText ( );
}
else if ( xmlStreamReader.getLocalName ( ).equals ( "value" ) && xmlStreamReader.getEventType ( ) == XMLStreamConstants.START_ELEMENT ) {
if ( name != null ) {
Object value = deserializeValue ( );
struct.put ( name , value );
}
}
else if ( CURRENT_TAG_NAME.equals ( "struct" ) && xmlStreamReader.getEventType ( ) == XMLStreamConstants.END_ELEMENT ) {
break;
}
}
return struct;
}
public static String skipXmlHeader ( String xml ) {
int startIndex = xml.indexOf ( "<?xml" );
if ( startIndex >= 0 ) {
int endIndex = xml.indexOf ( "?>" , startIndex );
if ( endIndex >= 0 ) {
return xml.substring ( endIndex + 2 );
}
}
return xml;
}
public void close ( ) throws XMLStreamException {
xmlStreamReader.close ( );
}
}

View file

@ -0,0 +1,166 @@
package dev.zontreck.ariaslib.xmlrpc;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.List;
import java.util.Map;
public class XmlRpcStreamWriter {
private static final String XML_VERSION = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
private static final String METHOD_CALL_START_TAG = "<methodCall>";
private static final String METHOD_CALL_END_TAG = "</methodCall>\n";
private static final String METHOD_NAME_START_TAG = "<methodName>";
private static final String METHOD_NAME_END_TAG = "</methodName>\n";
private static final String METHOD_RESPONSE_START_TAG = "<methodResponse>";
private static final String METHOD_RESPONSE_END_TAG = "</methodResponse>\n";
private static final String PARAMS_START_TAG = "<params>";
private static final String PARAMS_END_TAG = "</params>\n";
private static final String PARAM_START_TAG = "<param>";
private static final String PARAM_END_TAG = "</param>\n";
private static final String VALUE_START_TAG = "<value>";
private static final String VALUE_END_TAG = "</value>\n";
private static final String ARRAY_START_TAG = "<array>";
private static final String ARRAY_END_TAG = "</array>\n";
private static final String DATA_START_TAG = "<data>";
private static final String DATA_END_TAG = "</data>\n";
private static final String STRUCT_START_TAG = "<struct>";
private static final String STRUCT_END_TAG = "</struct>\n";
private static final String MEMBER_START_TAG = "<member>";
private static final String MEMBER_END_TAG = "</member>\n";
private static final String NAME_START_TAG = "<name>";
private static final String NAME_END_TAG = "</name>\n";
private Writer writer;
public XmlRpcStreamWriter ( OutputStream outputStream ) {
this.writer = new OutputStreamWriter ( outputStream );
}
public void writeMethodCall ( String methodName , List<Object> params ) throws IOException {
writer.write ( XML_VERSION );
writer.write ( METHOD_CALL_START_TAG );
writer.write ( METHOD_NAME_START_TAG );
writer.write ( methodName );
writer.write ( METHOD_NAME_END_TAG );
writer.write ( PARAMS_START_TAG );
if ( params != null ) {
for ( Object param : params ) {
writer.write ( PARAM_START_TAG );
writeValue ( param );
writer.write ( PARAM_END_TAG );
}
}
writer.write ( PARAMS_END_TAG );
writer.write ( METHOD_CALL_END_TAG );
writer.flush ( );
}
public void writeMethodResponse ( Object value ) throws IOException {
writer.write ( XML_VERSION );
writer.write ( METHOD_RESPONSE_START_TAG );
writer.write ( PARAMS_START_TAG );
writer.write ( PARAM_START_TAG );
writeValue ( value );
writer.write ( PARAM_END_TAG );
writer.write ( PARAMS_END_TAG );
writer.write ( METHOD_RESPONSE_END_TAG );
writer.flush ( );
}
private void writeValue ( Object value ) throws IOException {
if ( value == null ) {
writer.write ( VALUE_START_TAG );
writer.write ( "<nil/>" );
writer.write ( VALUE_END_TAG );
}
else if ( value instanceof String ) {
writer.write ( VALUE_START_TAG );
writer.write ( "<string>" );
writer.write ( escapeXml ( ( String ) value ) );
writer.write ( "</string>\n" );
writer.write ( VALUE_END_TAG );
}
else if ( value instanceof Integer ) {
writer.write ( VALUE_START_TAG );
writer.write ( "<i4>" );
writer.write ( value.toString ( ) );
writer.write ( "</i4>\n" );
writer.write ( VALUE_END_TAG );
} else if(value instanceof Long)
{
writer.write ( VALUE_START_TAG );
writer.write ( "<i8>" );
writer.write ( value.toString () ); // Save it as a int for now due to unclear handling
writer.write ( "</i8>\n" );
writer.write ( VALUE_END_TAG );
}
else if ( value instanceof Double ) {
writer.write ( VALUE_START_TAG );
writer.write ( "<double>" );
writer.write ( value.toString ( ) );
writer.write ( "</double>\n" );
writer.write ( VALUE_END_TAG );
}
else if ( value instanceof Boolean ) {
writer.write ( VALUE_START_TAG );
writer.write ( "<string>" );
writer.write ( value.toString ( ) );
writer.write ( "</string>\n" );
writer.write ( VALUE_END_TAG );
}
else if ( value instanceof List ) {
writer.write ( VALUE_START_TAG );
writer.write ( ARRAY_START_TAG );
writer.write ( DATA_START_TAG );
List<?> list = ( List<?> ) value;
for ( Object item : list ) {
writeValue ( item );
}
writer.write ( DATA_END_TAG );
writer.write ( ARRAY_END_TAG );
writer.write ( VALUE_END_TAG );
}
else if ( value instanceof Map ) {
writer.write ( VALUE_START_TAG );
writer.write ( STRUCT_START_TAG );
Map<?, ?> map = ( Map<?, ?> ) value;
for ( Map.Entry<?, ?> entry : map.entrySet ( ) ) {
writer.write ( MEMBER_START_TAG );
writer.write ( NAME_START_TAG );
writer.write ( escapeXml ( entry.getKey ( ).toString ( ) ) );
writer.write ( NAME_END_TAG );
writeValue ( entry.getValue ( ) );
writer.write ( MEMBER_END_TAG );
}
writer.write ( STRUCT_END_TAG );
writer.write ( VALUE_END_TAG );
}
else if(value instanceof Byte)
{
writer.write ( VALUE_START_TAG );
writer.write ( "<int>" );
writer.write ( value.toString () ); // Treat as a integer for now
writer.write ( "</int>\n" );
writer.write ( VALUE_END_TAG );
}
else {
throw new IllegalArgumentException ( "Unsupported data type: " + value.getClass ( ).getName ( ) );
}
}
private String escapeXml ( String value ) {
return value
.replace ( "&" , "&amp;" )
.replace ( "<" , "&lt;" )
.replace ( ">" , "&gt;" )
.replace ( "\"" , "&quot;" )
.replace ( "'" , "&apos;" );
}
public void close ( ) throws IOException {
writer.close ( );
}
}

View file

@ -0,0 +1,48 @@
package dev.zontreck.ariaslib.xmlrpc;
public class XmlRpcTokens
{
public final String ISO_DATETIME = "yyyyMMdd\\THH\\:mm\\:ss";
public final String BASE64 = "base64";
public final String STRING = "string";
public final String INT = "i4";
public final String ALT_INT = "int";
public final String DATETIME = "dateTime.iso8601";
public final String BOOLEAN = "boolean";
public final String VALUE = "value";
public final String NAME = "name";
public final String ARRAY = "array";
public final String DATA = "data";
public final String MEMBER = "member";
public final String STRUCT = "struct";
public final String DOUBLE = "double";
public final String PARAM = "param";
public final String PARAMS = "params";
public final String METHOD_CALL = "methodCall";
public final String METHOD_NAME = "methodName";
public final String METHOD_RESPONSE = "methodResponse";
public final String FAULT = "fault";
public final String FAULT_CODE = "faultCode";
public final String FAULT_STRING = "faultString";
}

View file

@ -0,0 +1,166 @@
package dev.zontreck.eventsbus;
import dev.zontreck.eventsbus.annotations.Priority;
import dev.zontreck.eventsbus.annotations.SingleshotEvent;
import dev.zontreck.eventsbus.annotations.Subscribe;
import dev.zontreck.eventsbus.events.EventBusReadyEvent;
import dev.zontreck.eventsbus.events.ResetEventBusEvent;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.*;
import java.util.stream.Collectors;
/**
* To be removed
* <br/>
* Use {EventDispatcher} instead
*/
@Deprecated()
public class Bus {
/**
* The main event bus!
*/
private static Bus Main;
static {
if(Main == null)
{
Main = new Bus("Main Event Bus", false);
}
}
public static boolean debug = false;
public final String BusName;
public final boolean UsesInstances;
public Bus(String name, boolean useInstances) {
BusName = name;
UsesInstances = useInstances;
Post(new EventBusReadyEvent());
}
public Map<Class<?>, List<EventContainer>> static_events = new HashMap<Class<?>, List<EventContainer>>();
public Map<Class<?>, List<EventContainer>> instanced_events = new HashMap<Class<?>, List<EventContainer>>();
public static <T> void Register(Class<T> clazz, T instance) {
List<Method> nonStaticMethods = Arrays.stream(clazz.getMethods())
.filter(x -> x.isAnnotationPresent(Subscribe.class))
.filter(x -> (x.getModifiers() & Modifier.STATIC) != Modifier.STATIC)
.collect(Collectors.toList());
List<Method> staticMethods = Arrays.stream(clazz.getMethods())
.filter(x -> x.isAnnotationPresent(Subscribe.class))
.filter(x -> (x.getModifiers() & Modifier.STATIC) == Modifier.STATIC)
.collect(Collectors.toList());
// Register the non-static methods if applicable
if (instance != null) {
for (Method m :
nonStaticMethods) {
EventContainer container = new EventContainer();
container.instance = instance;
container.method = m;
container.clazz = clazz;
if (m.isAnnotationPresent(Priority.class))
container.Level = m.getAnnotation(Priority.class).Level();
else container.Level = PriorityLevel.LOWEST;
Class<?> clz = m.getParameters()[0].getType();
container.IsSingleshot = m.isAnnotationPresent(SingleshotEvent.class);
if (Main.instanced_events.containsKey(clz))
Main.instanced_events.get(clz).add(container);
else {
Main.instanced_events.put(clz, new ArrayList<>());
Main.instanced_events.get(clz).add(container);
}
}
}
for (Method m : staticMethods) {
EventContainer container = new EventContainer();
container.instance = null;
container.method = m;
container.clazz = clazz;
if (m.isAnnotationPresent((Priority.class)))
container.Level = m.getAnnotation(Priority.class).Level();
else container.Level = PriorityLevel.LOWEST;
Class<?> clz = m.getParameters()[0].getType();
container.IsSingleshot = m.isAnnotationPresent(SingleshotEvent.class);
if (Main.static_events.containsKey(clz))
Main.static_events.get(clz).add(container);
else {
Main.static_events.put(clz, new ArrayList<>());
Main.static_events.get(clz).add(container);
}
}
}
/**
* Posts an event to the bus.
*
* @param event The event you wish to post
* @return True if the event was cancelled.
*/
public static boolean Post(Event event) {
for (PriorityLevel level :
PriorityLevel.values()) {
// Call each priority level in order of declaration
// Static first, then instanced
// At the end, this method will return the cancellation result.
try {
if (Main.static_events.containsKey(event.getClass())) {
EventContainer[] tempArray = (EventContainer[]) Main.static_events.get(event.getClass()).toArray();
for (EventContainer container : tempArray) {
if (container.invoke(event, level)) {
Main.static_events.get(event.getClass()).remove(container);
}
}
}
if (Main.instanced_events.containsKey(event.getClass())) {
EventContainer[] tempArray = (EventContainer[]) Main.instanced_events.get(event.getClass()).toArray();
for (EventContainer container : tempArray) {
if (container.invoke(event, level)) {
Main.instanced_events.get(event.getClass()).remove(container);
}
}
}
} catch (Exception e) {
}
}
return event.isCancelled();
}
/**
* Attempts to reset the Event Bus
*
* @return True if the bus was successfully reset (If not interrupts!)
* @see dev.zontreck.eventsbus.events.ResetEventBusEvent
*/
public static boolean Reset() {
if (!Post(new ResetEventBusEvent())) {
Main.static_events = new HashMap<>();
Main.instanced_events = new HashMap<>();
Post(new EventBusReadyEvent());
return true;
}
return false;
}
}

View file

@ -0,0 +1,95 @@
package dev.zontreck.eventsbus;
import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
@Deprecated
/**
* Used internally. Do not directly invoke
* <br/>
* Accessor is set Protected intentionally!!!!!!!!!
*/
class ClassScanner {
/**
* Start the process of scanning the classes and forcing them to load in
* <br/>
* This is used by the event dispatcher
*/
protected static void DoScan() {
// Scan all classes in the classpath
Set<Class<?>> scannedClasses = scanClasses();
// Force loading of all scanned classes
for (Class<?> clazz : scannedClasses) {
try {
// Load the class
Class.forName(clazz.getName());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
private static Set<Class<?>> scanClasses() {
String classpath = System.getProperty("java.class.path");
String[] classpathEntries = classpath.split(File.pathSeparator);
Set<Class<?>> scannedClasses = new HashSet<>();
for (String classpathEntry : classpathEntries) {
File file = new File(classpathEntry);
if (file.isDirectory()) {
scanClassesInDirectory(file, "", scannedClasses);
} else if (file.isFile() && classpathEntry.endsWith(".jar")) {
scanClassesInJar(file, scannedClasses);
}
}
return scannedClasses;
}
private static void scanClassesInDirectory(File directory, String packageName, Set<Class<?>> scannedClasses) {
File[] files = directory.listFiles();
if (files == null) {
return;
}
for (File file : files) {
if (file.isDirectory()) {
scanClassesInDirectory(file, packageName + "." + file.getName(), scannedClasses);
} else if (file.getName().endsWith(".class")) {
String className = packageName + "." + file.getName().substring(0, file.getName().length() - 6);
try {
Class<?> clazz = Class.forName(className);
scannedClasses.add(clazz);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}
private static void scanClassesInJar(File jarFile, Set<Class<?>> scannedClasses) {
try (JarFile jf = new JarFile(jarFile)) {
for (JarEntry entry : Collections.list(jf.entries())) {
if (entry.getName().endsWith(".class")) {
String className = entry.getName().replace("/", ".").substring(0, entry.getName().length() - 6);
try {
Class<?> clazz = Class.forName(className);
scannedClasses.add(clazz);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

View file

@ -0,0 +1,46 @@
package dev.zontreck.eventsbus;
import dev.zontreck.eventsbus.annotations.Cancellable;
import dev.zontreck.eventsbus.annotations.Priority;
public class Event {
private boolean cancelled = false;
/**
* Checks if the event can be cancelled.
*
* @return True if the cancellation annotation is present.
* @see Cancellable
*/
public boolean IsCancellable() {
Class<?> Current = this.getClass();
return Current.isAnnotationPresent(Cancellable.class);
}
/**
* Checks if the event is cancelled.
*
* @return False if the event cannot be cancelled; or
* The current cancellation status for the event
*/
public boolean isCancelled() {
if (!IsCancellable())
return false;
return cancelled;
}
/**
* Sets the cancelled status for the event
*
* @param cancel Whether the event should be marked as cancelled or not.
*/
public void setCancelled(boolean cancel) {
cancelled = cancel;
}
public PriorityLevel getPriorityLevel() {
Class<?> Current = this.getClass();
return Current.getAnnotation(Priority.class).Level();
}
}

View file

@ -0,0 +1,45 @@
package dev.zontreck.eventsbus;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class EventContainer {
public Class<?> clazz;
public Object instance;
/**
* The method that gets invoked, either statically, or via the instance.
*/
public Method method;
/**
* Indicates whether an event gets removed from the register after being invoked once.
*/
public boolean IsSingleshot;
/**
* The current method's priority level
*/
public PriorityLevel Level;
/**
* Invokes the event
*
* @param EventArg The event instance to pass to the subscribed function
* @param level Current priority level on the call loop. Will refuse to invoke if the priority level mismatches.
* @return True if the event was single shot and should be deregistered
* @throws InvocationTargetException
* @throws IllegalAccessException
*/
public boolean invoke(Event EventArg, PriorityLevel level) throws InvocationTargetException, IllegalAccessException {
if (Level != level) return false;
if (instance == null) {
method.invoke(null, EventArg);
} else {
method.invoke(instance, EventArg);
}
return IsSingleshot;
}
}

View file

@ -0,0 +1,124 @@
package dev.zontreck.eventsbus;
import dev.zontreck.eventsbus.annotations.EventSubscriber;
import dev.zontreck.eventsbus.annotations.Priority;
import dev.zontreck.eventsbus.annotations.SingleshotEvent;
import dev.zontreck.eventsbus.annotations.Subscribe;
import dev.zontreck.eventsbus.events.EventBusReadyEvent;
import dev.zontreck.eventsbus.events.ResetEventBusEvent;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class EventDispatcher
{
private static List<Method> singleshot = new ArrayList<>();
private static List<Class<?>> subscribers = new ArrayList<>();
/**
* Scans every Java class that is currently loaded. It then checks for Subscribe, and a proper parameter before posting the Event.
* The Event will only be posted if not cancelled using {@link Event#setCancelled(boolean)} and that {@link Subscribe#allowCancelled()} allows.
* @param event The event to post
* @return True if cancelled.
*/
public static boolean Post(Event event)
{
for(PriorityLevel level : PriorityLevel.values())
{
for(Class<?> clazz : subscribers)
{
for(Method M :clazz.getMethods())
{
if(!M.isAnnotationPresent(Subscribe.class)) continue;
Subscribe subscriber = M.getAnnotation(Subscribe.class);
boolean canPost=true;
Class<?> param = M.getParameterTypes()[0];
if(param == event.getClass())
{
if(M.isAnnotationPresent(SingleshotEvent.class))
{
if(singleshot.contains(M))
{
canPost=false;
}
}
} else canPost=false;
PriorityLevel eventPriotityLevel= PriorityLevel.HIGH; // Default
if(M.isAnnotationPresent(Priority.class))
{
Priority prio = M.getAnnotation(Priority.class);
eventPriotityLevel=prio.Level();
}
if(level != eventPriotityLevel)
{
canPost=false;
}
// Dispatch the event now
if(!canPost) continue;
if(!M.canAccess(null))
{
canPost=false;
System.out.println("ERROR: Even subscriber methods must be static and public");
}
try {
if(event.isCancelled() && !subscriber.allowCancelled())
continue;
else
M.invoke(null, event);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
}
}
}
}
return event.isCancelled();
}
/**
* Register a class
*/
public static void Register(Class<?> clazz)
{
if(clazz.isAnnotationPresent(EventSubscriber.class))
subscribers.add(clazz);
}
/**
* Resets the events system.
* <br/>
* This action clears the Singleshot list for the events that should only be invoked once. And rescans all classes incase new classes were dynamically loaded.
*/
public static void Reset()
{
Post(new ResetEventBusEvent());
subscribers.clear();
singleshot.clear();
Post(new EventBusReadyEvent());
}
}

View file

@ -0,0 +1,15 @@
package dev.zontreck.eventsbus;
/**
* Event priority level.
* <p>
* The higher the priority, the sooner it gets executed. High is executed after
* Highest.
*/
public enum PriorityLevel {
HIGHEST,
HIGH,
MEDIUM,
LOW,
LOWEST
}

View file

@ -0,0 +1,11 @@
package dev.zontreck.eventsbus.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = ElementType.TYPE)
public @interface Cancellable {
}

View file

@ -0,0 +1,11 @@
package dev.zontreck.eventsbus.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = ElementType.TYPE)
public @interface EventSubscriber {
}

View file

@ -0,0 +1,14 @@
package dev.zontreck.eventsbus.annotations;
import dev.zontreck.eventsbus.PriorityLevel;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = ElementType.METHOD)
public @interface Priority {
PriorityLevel Level();
}

View file

@ -0,0 +1,11 @@
package dev.zontreck.eventsbus.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = ElementType.METHOD)
public @interface SingleshotEvent {
}

View file

@ -0,0 +1,18 @@
package dev.zontreck.eventsbus.annotations;
import dev.zontreck.eventsbus.Event;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = ElementType.METHOD)
public @interface Subscribe {
/**
* Marks that the subscribed method will not receive the signal if the event was cancelled with {@link Event#setCancelled(boolean)}
*/
boolean allowCancelled();
}

View file

@ -0,0 +1,11 @@
package dev.zontreck.eventsbus.events;
import dev.zontreck.eventsbus.Event;
/**
* This event is sent out when the Event Bus is ready.
* <p>
* This is also dispatched when a reset occurs, prior to clearing the lists.
*/
public class EventBusReadyEvent extends Event {
}

View file

@ -0,0 +1,17 @@
package dev.zontreck.eventsbus.events;
import dev.zontreck.eventsbus.annotations.Cancellable;
import dev.zontreck.eventsbus.Event;
/**
* Posted when the event bus is about to be reset.
* <p>
* This event can be cancelled to prevent the reset.
* <p>
* The default behavior is: Allow Reset.
* <p>
* Recommended that handlers be implemented to re-register instances, and classes when a reset occurs.
*/
@Cancellable
public class ResetEventBusEvent extends Event {
}

View file

@ -0,0 +1,6 @@
package dev.zontreck.eventsbus.events;
import dev.zontreck.eventsbus.Event;
public class TickEvent extends Event {
}