v0
This commit is contained in:
82
src/com/hypixel/fastutil/FastCollection.java
Normal file
82
src/com/hypixel/fastutil/FastCollection.java
Normal file
@@ -0,0 +1,82 @@
|
||||
package com.hypixel.fastutil;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public interface FastCollection<E> extends Collection<E> {
|
||||
void forEachWithFloat(FastCollection.FastConsumerF<? super E> var1, float var2);
|
||||
|
||||
void forEachWithInt(FastCollection.FastConsumerI<? super E> var1, int var2);
|
||||
|
||||
void forEachWithLong(FastCollection.FastConsumerL<? super E> var1, long var2);
|
||||
|
||||
<A, B, C, D> void forEach(
|
||||
FastCollection.FastConsumerD9<? super E, A, B, C, D> var1,
|
||||
A var2,
|
||||
double var3,
|
||||
double var5,
|
||||
double var7,
|
||||
double var9,
|
||||
double var11,
|
||||
double var13,
|
||||
double var15,
|
||||
double var17,
|
||||
double var19,
|
||||
B var21,
|
||||
C var22,
|
||||
D var23
|
||||
);
|
||||
|
||||
<A, B, C, D> void forEach(
|
||||
FastCollection.FastConsumerD6<? super E, A, B, C, D> var1,
|
||||
A var2,
|
||||
double var3,
|
||||
double var5,
|
||||
double var7,
|
||||
double var9,
|
||||
double var11,
|
||||
double var13,
|
||||
B var15,
|
||||
C var16,
|
||||
D var17
|
||||
);
|
||||
|
||||
@FunctionalInterface
|
||||
public interface FastConsumerD6<A, B, C, D, E> {
|
||||
void accept(A var1, B var2, double var3, double var5, double var7, double var9, double var11, double var13, C var15, D var16, E var17);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface FastConsumerD9<A, B, C, D, E> {
|
||||
void accept(
|
||||
A var1,
|
||||
B var2,
|
||||
double var3,
|
||||
double var5,
|
||||
double var7,
|
||||
double var9,
|
||||
double var11,
|
||||
double var13,
|
||||
double var15,
|
||||
double var17,
|
||||
double var19,
|
||||
C var21,
|
||||
D var22,
|
||||
E var23
|
||||
);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface FastConsumerF<A> {
|
||||
void accept(A var1, float var2);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface FastConsumerI<A> {
|
||||
void accept(A var1, int var2);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface FastConsumerL<A> {
|
||||
void accept(A var1, long var2);
|
||||
}
|
||||
}
|
||||
6
src/com/hypixel/fastutil/bytes/Byte2ByteOperator.java
Normal file
6
src/com/hypixel/fastutil/bytes/Byte2ByteOperator.java
Normal file
@@ -0,0 +1,6 @@
|
||||
package com.hypixel.fastutil.bytes;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Byte2ByteOperator {
|
||||
byte apply(byte var1, byte var2);
|
||||
}
|
||||
6
src/com/hypixel/fastutil/bytes/Byte2CharOperator.java
Normal file
6
src/com/hypixel/fastutil/bytes/Byte2CharOperator.java
Normal file
@@ -0,0 +1,6 @@
|
||||
package com.hypixel.fastutil.bytes;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Byte2CharOperator {
|
||||
char apply(byte var1, char var2);
|
||||
}
|
||||
6
src/com/hypixel/fastutil/bytes/Byte2DoubleOperator.java
Normal file
6
src/com/hypixel/fastutil/bytes/Byte2DoubleOperator.java
Normal file
@@ -0,0 +1,6 @@
|
||||
package com.hypixel.fastutil.bytes;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Byte2DoubleOperator {
|
||||
double apply(byte var1, double var2);
|
||||
}
|
||||
6
src/com/hypixel/fastutil/bytes/Byte2FloatOperator.java
Normal file
6
src/com/hypixel/fastutil/bytes/Byte2FloatOperator.java
Normal file
@@ -0,0 +1,6 @@
|
||||
package com.hypixel.fastutil.bytes;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Byte2FloatOperator {
|
||||
float apply(byte var1, float var2);
|
||||
}
|
||||
6
src/com/hypixel/fastutil/bytes/Byte2IntOperator.java
Normal file
6
src/com/hypixel/fastutil/bytes/Byte2IntOperator.java
Normal file
@@ -0,0 +1,6 @@
|
||||
package com.hypixel.fastutil.bytes;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Byte2IntOperator {
|
||||
int apply(byte var1, int var2);
|
||||
}
|
||||
6
src/com/hypixel/fastutil/bytes/Byte2LongOperator.java
Normal file
6
src/com/hypixel/fastutil/bytes/Byte2LongOperator.java
Normal file
@@ -0,0 +1,6 @@
|
||||
package com.hypixel.fastutil.bytes;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Byte2LongOperator {
|
||||
long apply(byte var1, long var2);
|
||||
}
|
||||
10256
src/com/hypixel/fastutil/bytes/Byte2ObjectConcurrentHashMap.java
Normal file
10256
src/com/hypixel/fastutil/bytes/Byte2ObjectConcurrentHashMap.java
Normal file
File diff suppressed because it is too large
Load Diff
6
src/com/hypixel/fastutil/bytes/Byte2ObjectOperator.java
Normal file
6
src/com/hypixel/fastutil/bytes/Byte2ObjectOperator.java
Normal file
@@ -0,0 +1,6 @@
|
||||
package com.hypixel.fastutil.bytes;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Byte2ObjectOperator<V> {
|
||||
V apply(byte var1, V var2);
|
||||
}
|
||||
6
src/com/hypixel/fastutil/bytes/Byte2ShortOperator.java
Normal file
6
src/com/hypixel/fastutil/bytes/Byte2ShortOperator.java
Normal file
@@ -0,0 +1,6 @@
|
||||
package com.hypixel.fastutil.bytes;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Byte2ShortOperator {
|
||||
short apply(byte var1, short var2);
|
||||
}
|
||||
6
src/com/hypixel/fastutil/chars/Char2ByteOperator.java
Normal file
6
src/com/hypixel/fastutil/chars/Char2ByteOperator.java
Normal file
@@ -0,0 +1,6 @@
|
||||
package com.hypixel.fastutil.chars;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Char2ByteOperator {
|
||||
byte apply(char var1, byte var2);
|
||||
}
|
||||
6
src/com/hypixel/fastutil/chars/Char2CharOperator.java
Normal file
6
src/com/hypixel/fastutil/chars/Char2CharOperator.java
Normal file
@@ -0,0 +1,6 @@
|
||||
package com.hypixel.fastutil.chars;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Char2CharOperator {
|
||||
char apply(char var1, char var2);
|
||||
}
|
||||
6
src/com/hypixel/fastutil/chars/Char2DoubleOperator.java
Normal file
6
src/com/hypixel/fastutil/chars/Char2DoubleOperator.java
Normal file
@@ -0,0 +1,6 @@
|
||||
package com.hypixel.fastutil.chars;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Char2DoubleOperator {
|
||||
double apply(char var1, double var2);
|
||||
}
|
||||
6
src/com/hypixel/fastutil/chars/Char2FloatOperator.java
Normal file
6
src/com/hypixel/fastutil/chars/Char2FloatOperator.java
Normal file
@@ -0,0 +1,6 @@
|
||||
package com.hypixel.fastutil.chars;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Char2FloatOperator {
|
||||
float apply(char var1, float var2);
|
||||
}
|
||||
6
src/com/hypixel/fastutil/chars/Char2IntOperator.java
Normal file
6
src/com/hypixel/fastutil/chars/Char2IntOperator.java
Normal file
@@ -0,0 +1,6 @@
|
||||
package com.hypixel.fastutil.chars;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Char2IntOperator {
|
||||
int apply(char var1, int var2);
|
||||
}
|
||||
6
src/com/hypixel/fastutil/chars/Char2LongOperator.java
Normal file
6
src/com/hypixel/fastutil/chars/Char2LongOperator.java
Normal file
@@ -0,0 +1,6 @@
|
||||
package com.hypixel.fastutil.chars;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Char2LongOperator {
|
||||
long apply(char var1, long var2);
|
||||
}
|
||||
10256
src/com/hypixel/fastutil/chars/Char2ObjectConcurrentHashMap.java
Normal file
10256
src/com/hypixel/fastutil/chars/Char2ObjectConcurrentHashMap.java
Normal file
File diff suppressed because it is too large
Load Diff
6
src/com/hypixel/fastutil/chars/Char2ObjectOperator.java
Normal file
6
src/com/hypixel/fastutil/chars/Char2ObjectOperator.java
Normal file
@@ -0,0 +1,6 @@
|
||||
package com.hypixel.fastutil.chars;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Char2ObjectOperator<V> {
|
||||
V apply(char var1, V var2);
|
||||
}
|
||||
6
src/com/hypixel/fastutil/chars/Char2ShortOperator.java
Normal file
6
src/com/hypixel/fastutil/chars/Char2ShortOperator.java
Normal file
@@ -0,0 +1,6 @@
|
||||
package com.hypixel.fastutil.chars;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Char2ShortOperator {
|
||||
short apply(char var1, short var2);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package com.hypixel.fastutil.doubles;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Double2ByteOperator {
|
||||
byte apply(double var1, byte var3);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package com.hypixel.fastutil.doubles;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Double2CharOperator {
|
||||
char apply(double var1, char var3);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package com.hypixel.fastutil.doubles;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Double2DoubleOperator {
|
||||
double apply(double var1, double var3);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package com.hypixel.fastutil.doubles;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Double2FloatOperator {
|
||||
float apply(double var1, float var3);
|
||||
}
|
||||
6
src/com/hypixel/fastutil/doubles/Double2IntOperator.java
Normal file
6
src/com/hypixel/fastutil/doubles/Double2IntOperator.java
Normal file
@@ -0,0 +1,6 @@
|
||||
package com.hypixel.fastutil.doubles;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Double2IntOperator {
|
||||
int apply(double var1, int var3);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package com.hypixel.fastutil.doubles;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Double2LongOperator {
|
||||
long apply(double var1, long var3);
|
||||
}
|
||||
10282
src/com/hypixel/fastutil/doubles/Double2ObjectConcurrentHashMap.java
Normal file
10282
src/com/hypixel/fastutil/doubles/Double2ObjectConcurrentHashMap.java
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,6 @@
|
||||
package com.hypixel.fastutil.doubles;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Double2ObjectOperator<V> {
|
||||
V apply(double var1, V var3);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package com.hypixel.fastutil.doubles;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Double2ShortOperator {
|
||||
short apply(double var1, short var3);
|
||||
}
|
||||
6
src/com/hypixel/fastutil/floats/Float2ByteOperator.java
Normal file
6
src/com/hypixel/fastutil/floats/Float2ByteOperator.java
Normal file
@@ -0,0 +1,6 @@
|
||||
package com.hypixel.fastutil.floats;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Float2ByteOperator {
|
||||
byte apply(float var1, byte var2);
|
||||
}
|
||||
6
src/com/hypixel/fastutil/floats/Float2CharOperator.java
Normal file
6
src/com/hypixel/fastutil/floats/Float2CharOperator.java
Normal file
@@ -0,0 +1,6 @@
|
||||
package com.hypixel.fastutil.floats;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Float2CharOperator {
|
||||
char apply(float var1, char var2);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package com.hypixel.fastutil.floats;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Float2DoubleOperator {
|
||||
double apply(float var1, double var2);
|
||||
}
|
||||
6
src/com/hypixel/fastutil/floats/Float2FloatOperator.java
Normal file
6
src/com/hypixel/fastutil/floats/Float2FloatOperator.java
Normal file
@@ -0,0 +1,6 @@
|
||||
package com.hypixel.fastutil.floats;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Float2FloatOperator {
|
||||
float apply(float var1, float var2);
|
||||
}
|
||||
6
src/com/hypixel/fastutil/floats/Float2IntOperator.java
Normal file
6
src/com/hypixel/fastutil/floats/Float2IntOperator.java
Normal file
@@ -0,0 +1,6 @@
|
||||
package com.hypixel.fastutil.floats;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Float2IntOperator {
|
||||
int apply(float var1, int var2);
|
||||
}
|
||||
6
src/com/hypixel/fastutil/floats/Float2LongOperator.java
Normal file
6
src/com/hypixel/fastutil/floats/Float2LongOperator.java
Normal file
@@ -0,0 +1,6 @@
|
||||
package com.hypixel.fastutil.floats;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Float2LongOperator {
|
||||
long apply(float var1, long var2);
|
||||
}
|
||||
10267
src/com/hypixel/fastutil/floats/Float2ObjectConcurrentHashMap.java
Normal file
10267
src/com/hypixel/fastutil/floats/Float2ObjectConcurrentHashMap.java
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,6 @@
|
||||
package com.hypixel.fastutil.floats;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Float2ObjectOperator<V> {
|
||||
V apply(float var1, V var2);
|
||||
}
|
||||
6
src/com/hypixel/fastutil/floats/Float2ShortOperator.java
Normal file
6
src/com/hypixel/fastutil/floats/Float2ShortOperator.java
Normal file
@@ -0,0 +1,6 @@
|
||||
package com.hypixel.fastutil.floats;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Float2ShortOperator {
|
||||
short apply(float var1, short var2);
|
||||
}
|
||||
6
src/com/hypixel/fastutil/ints/Int2ByteOperator.java
Normal file
6
src/com/hypixel/fastutil/ints/Int2ByteOperator.java
Normal file
@@ -0,0 +1,6 @@
|
||||
package com.hypixel.fastutil.ints;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Int2ByteOperator {
|
||||
byte apply(int var1, byte var2);
|
||||
}
|
||||
6
src/com/hypixel/fastutil/ints/Int2CharOperator.java
Normal file
6
src/com/hypixel/fastutil/ints/Int2CharOperator.java
Normal file
@@ -0,0 +1,6 @@
|
||||
package com.hypixel.fastutil.ints;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Int2CharOperator {
|
||||
char apply(int var1, char var2);
|
||||
}
|
||||
6
src/com/hypixel/fastutil/ints/Int2DoubleOperator.java
Normal file
6
src/com/hypixel/fastutil/ints/Int2DoubleOperator.java
Normal file
@@ -0,0 +1,6 @@
|
||||
package com.hypixel.fastutil.ints;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Int2DoubleOperator {
|
||||
double apply(int var1, double var2);
|
||||
}
|
||||
6
src/com/hypixel/fastutil/ints/Int2FloatOperator.java
Normal file
6
src/com/hypixel/fastutil/ints/Int2FloatOperator.java
Normal file
@@ -0,0 +1,6 @@
|
||||
package com.hypixel.fastutil.ints;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Int2FloatOperator {
|
||||
float apply(int var1, float var2);
|
||||
}
|
||||
6
src/com/hypixel/fastutil/ints/Int2IntOperator.java
Normal file
6
src/com/hypixel/fastutil/ints/Int2IntOperator.java
Normal file
@@ -0,0 +1,6 @@
|
||||
package com.hypixel.fastutil.ints;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Int2IntOperator {
|
||||
int apply(int var1, int var2);
|
||||
}
|
||||
6
src/com/hypixel/fastutil/ints/Int2LongOperator.java
Normal file
6
src/com/hypixel/fastutil/ints/Int2LongOperator.java
Normal file
@@ -0,0 +1,6 @@
|
||||
package com.hypixel.fastutil.ints;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Int2LongOperator {
|
||||
long apply(int var1, long var2);
|
||||
}
|
||||
10248
src/com/hypixel/fastutil/ints/Int2ObjectConcurrentHashMap.java
Normal file
10248
src/com/hypixel/fastutil/ints/Int2ObjectConcurrentHashMap.java
Normal file
File diff suppressed because it is too large
Load Diff
6
src/com/hypixel/fastutil/ints/Int2ObjectOperator.java
Normal file
6
src/com/hypixel/fastutil/ints/Int2ObjectOperator.java
Normal file
@@ -0,0 +1,6 @@
|
||||
package com.hypixel.fastutil.ints;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Int2ObjectOperator<V> {
|
||||
V apply(int var1, V var2);
|
||||
}
|
||||
6
src/com/hypixel/fastutil/ints/Int2ShortOperator.java
Normal file
6
src/com/hypixel/fastutil/ints/Int2ShortOperator.java
Normal file
@@ -0,0 +1,6 @@
|
||||
package com.hypixel.fastutil.ints;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Int2ShortOperator {
|
||||
short apply(int var1, short var2);
|
||||
}
|
||||
6
src/com/hypixel/fastutil/longs/Long2ByteOperator.java
Normal file
6
src/com/hypixel/fastutil/longs/Long2ByteOperator.java
Normal file
@@ -0,0 +1,6 @@
|
||||
package com.hypixel.fastutil.longs;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Long2ByteOperator {
|
||||
byte apply(long var1, byte var3);
|
||||
}
|
||||
6
src/com/hypixel/fastutil/longs/Long2CharOperator.java
Normal file
6
src/com/hypixel/fastutil/longs/Long2CharOperator.java
Normal file
@@ -0,0 +1,6 @@
|
||||
package com.hypixel.fastutil.longs;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Long2CharOperator {
|
||||
char apply(long var1, char var3);
|
||||
}
|
||||
6
src/com/hypixel/fastutil/longs/Long2DoubleOperator.java
Normal file
6
src/com/hypixel/fastutil/longs/Long2DoubleOperator.java
Normal file
@@ -0,0 +1,6 @@
|
||||
package com.hypixel.fastutil.longs;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Long2DoubleOperator {
|
||||
double apply(long var1, double var3);
|
||||
}
|
||||
6
src/com/hypixel/fastutil/longs/Long2FloatOperator.java
Normal file
6
src/com/hypixel/fastutil/longs/Long2FloatOperator.java
Normal file
@@ -0,0 +1,6 @@
|
||||
package com.hypixel.fastutil.longs;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Long2FloatOperator {
|
||||
float apply(long var1, float var3);
|
||||
}
|
||||
6
src/com/hypixel/fastutil/longs/Long2IntOperator.java
Normal file
6
src/com/hypixel/fastutil/longs/Long2IntOperator.java
Normal file
@@ -0,0 +1,6 @@
|
||||
package com.hypixel.fastutil.longs;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Long2IntOperator {
|
||||
int apply(long var1, int var3);
|
||||
}
|
||||
6
src/com/hypixel/fastutil/longs/Long2LongOperator.java
Normal file
6
src/com/hypixel/fastutil/longs/Long2LongOperator.java
Normal file
@@ -0,0 +1,6 @@
|
||||
package com.hypixel.fastutil.longs;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Long2LongOperator {
|
||||
long apply(long var1, long var3);
|
||||
}
|
||||
10262
src/com/hypixel/fastutil/longs/Long2ObjectConcurrentHashMap.java
Normal file
10262
src/com/hypixel/fastutil/longs/Long2ObjectConcurrentHashMap.java
Normal file
File diff suppressed because it is too large
Load Diff
6
src/com/hypixel/fastutil/longs/Long2ObjectOperator.java
Normal file
6
src/com/hypixel/fastutil/longs/Long2ObjectOperator.java
Normal file
@@ -0,0 +1,6 @@
|
||||
package com.hypixel.fastutil.longs;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Long2ObjectOperator<V> {
|
||||
V apply(long var1, V var3);
|
||||
}
|
||||
6
src/com/hypixel/fastutil/longs/Long2ShortOperator.java
Normal file
6
src/com/hypixel/fastutil/longs/Long2ShortOperator.java
Normal file
@@ -0,0 +1,6 @@
|
||||
package com.hypixel.fastutil.longs;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Long2ShortOperator {
|
||||
short apply(long var1, short var3);
|
||||
}
|
||||
6
src/com/hypixel/fastutil/shorts/Short2ByteOperator.java
Normal file
6
src/com/hypixel/fastutil/shorts/Short2ByteOperator.java
Normal file
@@ -0,0 +1,6 @@
|
||||
package com.hypixel.fastutil.shorts;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Short2ByteOperator {
|
||||
byte apply(short var1, byte var2);
|
||||
}
|
||||
6
src/com/hypixel/fastutil/shorts/Short2CharOperator.java
Normal file
6
src/com/hypixel/fastutil/shorts/Short2CharOperator.java
Normal file
@@ -0,0 +1,6 @@
|
||||
package com.hypixel.fastutil.shorts;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Short2CharOperator {
|
||||
char apply(short var1, char var2);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package com.hypixel.fastutil.shorts;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Short2DoubleOperator {
|
||||
double apply(short var1, double var2);
|
||||
}
|
||||
6
src/com/hypixel/fastutil/shorts/Short2FloatOperator.java
Normal file
6
src/com/hypixel/fastutil/shorts/Short2FloatOperator.java
Normal file
@@ -0,0 +1,6 @@
|
||||
package com.hypixel.fastutil.shorts;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Short2FloatOperator {
|
||||
float apply(short var1, float var2);
|
||||
}
|
||||
6
src/com/hypixel/fastutil/shorts/Short2IntOperator.java
Normal file
6
src/com/hypixel/fastutil/shorts/Short2IntOperator.java
Normal file
@@ -0,0 +1,6 @@
|
||||
package com.hypixel.fastutil.shorts;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Short2IntOperator {
|
||||
int apply(short var1, int var2);
|
||||
}
|
||||
6
src/com/hypixel/fastutil/shorts/Short2LongOperator.java
Normal file
6
src/com/hypixel/fastutil/shorts/Short2LongOperator.java
Normal file
@@ -0,0 +1,6 @@
|
||||
package com.hypixel.fastutil.shorts;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Short2LongOperator {
|
||||
long apply(short var1, long var2);
|
||||
}
|
||||
10267
src/com/hypixel/fastutil/shorts/Short2ObjectConcurrentHashMap.java
Normal file
10267
src/com/hypixel/fastutil/shorts/Short2ObjectConcurrentHashMap.java
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,6 @@
|
||||
package com.hypixel.fastutil.shorts;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Short2ObjectOperator<V> {
|
||||
V apply(short var1, V var2);
|
||||
}
|
||||
6
src/com/hypixel/fastutil/shorts/Short2ShortOperator.java
Normal file
6
src/com/hypixel/fastutil/shorts/Short2ShortOperator.java
Normal file
@@ -0,0 +1,6 @@
|
||||
package com.hypixel.fastutil.shorts;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Short2ShortOperator {
|
||||
short apply(short var1, short var2);
|
||||
}
|
||||
18
src/com/hypixel/fastutil/util/SneakyThrow.java
Normal file
18
src/com/hypixel/fastutil/util/SneakyThrow.java
Normal file
@@ -0,0 +1,18 @@
|
||||
package com.hypixel.fastutil.util;
|
||||
|
||||
public class SneakyThrow {
|
||||
public SneakyThrow() {
|
||||
}
|
||||
|
||||
public static RuntimeException sneakyThrow(Throwable t) {
|
||||
if (t == null) {
|
||||
throw new NullPointerException("t");
|
||||
} else {
|
||||
return sneakyThrow0(t);
|
||||
}
|
||||
}
|
||||
|
||||
private static <T extends Throwable> T sneakyThrow0(Throwable t) throws T {
|
||||
throw t;
|
||||
}
|
||||
}
|
||||
55
src/com/hypixel/fastutil/util/TLRUtil.java
Normal file
55
src/com/hypixel/fastutil/util/TLRUtil.java
Normal file
@@ -0,0 +1,55 @@
|
||||
package com.hypixel.fastutil.util;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import sun.misc.Unsafe;
|
||||
|
||||
public class TLRUtil {
|
||||
private static final Unsafe UNSAFE;
|
||||
private static final long PROBE;
|
||||
|
||||
public TLRUtil() {
|
||||
}
|
||||
|
||||
public static void localInit() {
|
||||
ThreadLocalRandom.current();
|
||||
}
|
||||
|
||||
public static int getProbe() {
|
||||
return UNSAFE.getInt(Thread.currentThread(), PROBE);
|
||||
}
|
||||
|
||||
public static int advanceProbe(int probe) {
|
||||
probe ^= probe << 13;
|
||||
probe ^= probe >>> 17;
|
||||
probe ^= probe << 5;
|
||||
UNSAFE.putInt(Thread.currentThread(), PROBE, probe);
|
||||
return probe;
|
||||
}
|
||||
|
||||
static {
|
||||
Unsafe instance;
|
||||
try {
|
||||
Field field = Unsafe.class.getDeclaredField("theUnsafe");
|
||||
field.setAccessible(true);
|
||||
instance = (Unsafe)field.get(null);
|
||||
} catch (Exception var5) {
|
||||
try {
|
||||
Constructor<Unsafe> c = Unsafe.class.getDeclaredConstructor();
|
||||
c.setAccessible(true);
|
||||
instance = c.newInstance();
|
||||
} catch (Exception var4) {
|
||||
throw SneakyThrow.sneakyThrow(var4);
|
||||
}
|
||||
}
|
||||
|
||||
UNSAFE = instance;
|
||||
|
||||
try {
|
||||
PROBE = UNSAFE.objectFieldOffset(Thread.class.getDeclaredField("threadLocalRandomProbe"));
|
||||
} catch (NoSuchFieldException var3) {
|
||||
throw SneakyThrow.sneakyThrow(var3);
|
||||
}
|
||||
}
|
||||
}
|
||||
59
src/com/hypixel/hytale/LateMain.java
Normal file
59
src/com/hypixel/hytale/LateMain.java
Normal file
@@ -0,0 +1,59 @@
|
||||
package com.hypixel.hytale;
|
||||
|
||||
import com.hypixel.hytale.logger.HytaleLogger;
|
||||
import com.hypixel.hytale.logger.backend.HytaleFileHandler;
|
||||
import com.hypixel.hytale.logger.backend.HytaleLoggerBackend;
|
||||
import com.hypixel.hytale.logger.sentry.SkipSentryException;
|
||||
import com.hypixel.hytale.server.core.HytaleServer;
|
||||
import com.hypixel.hytale.server.core.HytaleServerConfig;
|
||||
import com.hypixel.hytale.server.core.Options;
|
||||
import io.sentry.Sentry;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.logging.Level;
|
||||
|
||||
public class LateMain {
|
||||
public LateMain() {
|
||||
}
|
||||
|
||||
public static void lateMain(String[] args) {
|
||||
try {
|
||||
if (!Options.parse(args)) {
|
||||
HytaleLogger.init();
|
||||
HytaleFileHandler.INSTANCE.enable();
|
||||
HytaleLogger.replaceStd();
|
||||
HytaleLoggerBackend.LOG_LEVEL_LOADER = name -> {
|
||||
for (Entry<String, Level> e : Options.getOptionSet().valuesOf(Options.LOG_LEVELS)) {
|
||||
if (name.equals(e.getKey())) {
|
||||
return e.getValue();
|
||||
}
|
||||
}
|
||||
|
||||
HytaleServer hytaleServer = HytaleServer.get();
|
||||
if (hytaleServer != null) {
|
||||
HytaleServerConfig config = hytaleServer.getConfig();
|
||||
if (config != null) {
|
||||
Level configLevel = config.getLogLevels().get(name);
|
||||
if (configLevel != null) {
|
||||
return configLevel;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Options.getOptionSet().has(Options.SHUTDOWN_AFTER_VALIDATE) ? Level.WARNING : null;
|
||||
};
|
||||
if (Options.getOptionSet().has(Options.SHUTDOWN_AFTER_VALIDATE)) {
|
||||
HytaleLoggerBackend.reloadLogLevels();
|
||||
}
|
||||
|
||||
new HytaleServer();
|
||||
}
|
||||
} catch (Throwable var2) {
|
||||
if (!SkipSentryException.hasSkipSentry(var2)) {
|
||||
Sentry.captureException(var2);
|
||||
}
|
||||
|
||||
var2.printStackTrace();
|
||||
throw new RuntimeException("Failed to create HytaleServer", var2);
|
||||
}
|
||||
}
|
||||
}
|
||||
78
src/com/hypixel/hytale/Main.java
Normal file
78
src/com/hypixel/hytale/Main.java
Normal file
@@ -0,0 +1,78 @@
|
||||
package com.hypixel.hytale;
|
||||
|
||||
import com.hypixel.hytale.plugin.early.EarlyPluginLoader;
|
||||
import com.hypixel.hytale.plugin.early.TransformingClassLoader;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Locale;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public final class Main {
|
||||
public Main() {
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
Locale.setDefault(Locale.ENGLISH);
|
||||
System.setProperty("java.awt.headless", "true");
|
||||
System.setProperty("file.encoding", "UTF-8");
|
||||
EarlyPluginLoader.loadEarlyPlugins(args);
|
||||
if (EarlyPluginLoader.hasTransformers()) {
|
||||
launchWithTransformingClassLoader(args);
|
||||
} else {
|
||||
LateMain.lateMain(args);
|
||||
}
|
||||
}
|
||||
|
||||
private static void launchWithTransformingClassLoader(@Nonnull String[] args) {
|
||||
try {
|
||||
URL[] urls = getClasspathUrls();
|
||||
ClassLoader appClassLoader = Main.class.getClassLoader();
|
||||
TransformingClassLoader transformingClassLoader = new TransformingClassLoader(
|
||||
urls, EarlyPluginLoader.getTransformers(), appClassLoader.getParent(), appClassLoader
|
||||
);
|
||||
Thread.currentThread().setContextClassLoader(transformingClassLoader);
|
||||
Class<?> lateMainClass = transformingClassLoader.loadClass("com.hypixel.hytale.LateMain");
|
||||
Method mainMethod = lateMainClass.getMethod("lateMain", String[].class);
|
||||
mainMethod.invoke(null, args);
|
||||
} catch (NoSuchMethodException | IllegalAccessException | ClassNotFoundException var6) {
|
||||
throw new RuntimeException("Failed to launch with transforming classloader", var6);
|
||||
} catch (InvocationTargetException var7) {
|
||||
Throwable cause = var7.getCause();
|
||||
if (cause instanceof RuntimeException re) {
|
||||
throw re;
|
||||
} else if (cause instanceof Error err) {
|
||||
throw err;
|
||||
} else {
|
||||
throw new RuntimeException("LateMain.lateMain() threw an exception", cause);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static URL[] getClasspathUrls() {
|
||||
if (Main.class.getClassLoader() instanceof URLClassLoader urlClassLoader) {
|
||||
return urlClassLoader.getURLs();
|
||||
} else {
|
||||
ObjectArrayList<URL> urls = new ObjectArrayList<>();
|
||||
String classpath = System.getProperty("java.class.path");
|
||||
if (classpath != null && !classpath.isEmpty()) {
|
||||
for (String pathStr : classpath.split(System.getProperty("path.separator"))) {
|
||||
try {
|
||||
Path path = Path.of(pathStr);
|
||||
if (Files.exists(path)) {
|
||||
urls.add(path.toUri().toURL());
|
||||
}
|
||||
} catch (Exception var8) {
|
||||
System.err.println("[EarlyPlugin] Failed to parse classpath entry: " + pathStr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return urls.toArray(URL[]::new);
|
||||
}
|
||||
}
|
||||
}
|
||||
11
src/com/hypixel/hytale/assetstore/AssetConstants.java
Normal file
11
src/com/hypixel/hytale/assetstore/AssetConstants.java
Normal file
@@ -0,0 +1,11 @@
|
||||
package com.hypixel.hytale.assetstore;
|
||||
|
||||
public class AssetConstants {
|
||||
public static final int EXPECTED_CHILDREN_PER_ASSET = 3;
|
||||
public static final int EXPECTED_ASSETS_PER_PATH = 1;
|
||||
public static final int EXPECTED_VALUES_PER_TAG = 3;
|
||||
public static final int EXPECTED_ASSETS_PER_TAG = 3;
|
||||
|
||||
public AssetConstants() {
|
||||
}
|
||||
}
|
||||
279
src/com/hypixel/hytale/assetstore/AssetExtraInfo.java
Normal file
279
src/com/hypixel/hytale/assetstore/AssetExtraInfo.java
Normal file
@@ -0,0 +1,279 @@
|
||||
package com.hypixel.hytale.assetstore;
|
||||
|
||||
import com.hypixel.hytale.assetstore.map.JsonAssetWithMap;
|
||||
import com.hypixel.hytale.codec.ExtraInfo;
|
||||
import com.hypixel.hytale.common.util.ArrayUtil;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMaps;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
|
||||
import it.unimi.dsi.fastutil.ints.IntSet;
|
||||
import it.unimi.dsi.fastutil.ints.IntSets;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.function.Function;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class AssetExtraInfo<K> extends ExtraInfo {
|
||||
@Nullable
|
||||
private final Path assetPath;
|
||||
private final AssetExtraInfo.Data data;
|
||||
|
||||
public AssetExtraInfo(AssetExtraInfo.Data data) {
|
||||
super(Integer.MAX_VALUE, AssetValidationResults::new);
|
||||
this.assetPath = null;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public AssetExtraInfo(Path assetPath, AssetExtraInfo.Data data) {
|
||||
super(Integer.MAX_VALUE, AssetValidationResults::new);
|
||||
this.assetPath = assetPath;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public String generateKey() {
|
||||
return "*" + this.getKey() + "_" + this.peekKey('_');
|
||||
}
|
||||
|
||||
public K getKey() {
|
||||
return (K)this.getData().getKey();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Path getAssetPath() {
|
||||
return this.assetPath;
|
||||
}
|
||||
|
||||
public AssetExtraInfo.Data getData() {
|
||||
return this.data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendDetailsTo(@Nonnull StringBuilder sb) {
|
||||
sb.append("Id: ").append(this.getKey()).append("\n");
|
||||
if (this.assetPath != null) {
|
||||
sb.append("Path: ").append(this.assetPath).append("\n");
|
||||
}
|
||||
}
|
||||
|
||||
public AssetValidationResults getValidationResults() {
|
||||
return (AssetValidationResults)super.getValidationResults();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public String toString() {
|
||||
return "AssetExtraInfo{assetPath=" + this.assetPath + ", data=" + this.data + "} " + super.toString();
|
||||
}
|
||||
|
||||
public static class Data {
|
||||
public static final char TAG_VALUE_SEPARATOR = '=';
|
||||
private Map<Class<? extends JsonAssetWithMap>, List<Object>> containedAssets;
|
||||
private Map<Class<? extends JsonAssetWithMap>, List<RawAsset<Object>>> containedRawAssets;
|
||||
@Nullable
|
||||
private AssetExtraInfo.Data containerData;
|
||||
private Class<? extends JsonAsset<?>> assetClass;
|
||||
private Object key;
|
||||
private Object parentKey;
|
||||
private final Map<String, String[]> rawTags = new HashMap<>(0);
|
||||
private final Int2ObjectMap<IntSet> tagStorage = new Int2ObjectOpenHashMap<>(0);
|
||||
private final Int2ObjectMap<IntSet> unmodifiableTagStorage = new Int2ObjectOpenHashMap<>(0);
|
||||
private final IntSet expandedTagStorage = new IntOpenHashSet(0);
|
||||
private final IntSet unmodifiableExpandedTagStorage = IntSets.unmodifiable(this.expandedTagStorage);
|
||||
|
||||
public <K> Data(Class<? extends JsonAsset<K>> assetClass, K key, K parentKey) {
|
||||
this.assetClass = assetClass;
|
||||
this.key = key;
|
||||
this.parentKey = parentKey;
|
||||
}
|
||||
|
||||
public <K> Data(@Nullable AssetExtraInfo.Data containerData, Class<? extends JsonAsset<K>> aClass, K key, K parentKey, boolean inheritContainerTags) {
|
||||
this(aClass, key, parentKey);
|
||||
this.containerData = containerData;
|
||||
if (containerData != null && inheritContainerTags) {
|
||||
this.putTags(containerData.rawTags);
|
||||
}
|
||||
}
|
||||
|
||||
public Class<? extends JsonAsset<?>> getAssetClass() {
|
||||
return this.assetClass;
|
||||
}
|
||||
|
||||
public Object getKey() {
|
||||
return this.key;
|
||||
}
|
||||
|
||||
public Object getParentKey() {
|
||||
return this.parentKey;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public AssetExtraInfo.Data getRootContainerData() {
|
||||
AssetExtraInfo.Data temp = this;
|
||||
|
||||
while (temp.containerData != null) {
|
||||
temp = temp.containerData;
|
||||
}
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public AssetExtraInfo.Data getContainerData() {
|
||||
return this.containerData;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public <K> K getContainerKey(Class<? extends JsonAsset<K>> aClass) {
|
||||
if (this.containerData == null) {
|
||||
return null;
|
||||
} else {
|
||||
return (K)(this.containerData.assetClass.equals(aClass) ? this.containerData.key : this.containerData.getContainerKey(aClass));
|
||||
}
|
||||
}
|
||||
|
||||
public void putTags(@Nonnull Map<String, String[]> tags) {
|
||||
for (Entry<String, String[]> entry : tags.entrySet()) {
|
||||
String tag = entry.getKey().intern();
|
||||
this.rawTags.merge(tag, entry.getValue(), ArrayUtil::combine);
|
||||
IntSet tagIndexes = this.ensureTag(tag);
|
||||
|
||||
for (String value : entry.getValue()) {
|
||||
tagIndexes.add(AssetRegistry.getOrCreateTagIndex(value));
|
||||
this.ensureTag(value);
|
||||
this.rawTags.putIfAbsent(value, ArrayUtil.EMPTY_STRING_ARRAY);
|
||||
String valueTag = (tag + "=" + value).intern();
|
||||
this.rawTags.putIfAbsent(valueTag, ArrayUtil.EMPTY_STRING_ARRAY);
|
||||
this.ensureTag(valueTag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public Map<String, String[]> getRawTags() {
|
||||
return Collections.unmodifiableMap(this.rawTags);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public Int2ObjectMap<IntSet> getTags() {
|
||||
return Int2ObjectMaps.unmodifiable(this.unmodifiableTagStorage);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public IntSet getExpandedTagIndexes() {
|
||||
return this.unmodifiableExpandedTagStorage;
|
||||
}
|
||||
|
||||
public IntSet getTag(int tagIndex) {
|
||||
return this.unmodifiableTagStorage.getOrDefault(tagIndex, IntSets.EMPTY_SET);
|
||||
}
|
||||
|
||||
public <K, T extends JsonAssetWithMap<K, M>, M extends AssetMap<K, T>> void addContainedAsset(Class<T> assetClass, T asset) {
|
||||
if (this.containedAssets == null) {
|
||||
this.containedAssets = new HashMap<>();
|
||||
}
|
||||
|
||||
this.containedAssets.computeIfAbsent(assetClass, k -> new ArrayList<>()).add(asset);
|
||||
}
|
||||
|
||||
public <K, T extends JsonAssetWithMap<K, M>, M extends AssetMap<K, T>> void addContainedAsset(Class<T> assetClass, RawAsset<K> rawAsset) {
|
||||
if (this.containedRawAssets == null) {
|
||||
this.containedRawAssets = new HashMap<>();
|
||||
}
|
||||
|
||||
this.containedRawAssets.computeIfAbsent(assetClass, k -> new ArrayList<>()).add(rawAsset);
|
||||
}
|
||||
|
||||
public <K> void fetchContainedAssets(K key, @Nonnull Map<Class<? extends JsonAssetWithMap>, Map<K, List<Object>>> containedAssets) {
|
||||
if (this.containedAssets != null) {
|
||||
for (Entry<Class<? extends JsonAssetWithMap>, List<Object>> entry : this.containedAssets.entrySet()) {
|
||||
containedAssets.computeIfAbsent(entry.getKey(), k -> new HashMap<>()).computeIfAbsent(key, k -> new ArrayList<>(3)).addAll(entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public <K> void fetchContainedRawAssets(K key, @Nonnull Map<Class<? extends JsonAssetWithMap>, Map<K, List<RawAsset<Object>>>> containedAssets) {
|
||||
if (this.containedRawAssets != null) {
|
||||
for (Entry<Class<? extends JsonAssetWithMap>, List<RawAsset<Object>>> entry : this.containedRawAssets.entrySet()) {
|
||||
containedAssets.computeIfAbsent(entry.getKey(), k -> new HashMap<>()).computeIfAbsent(key, k -> new ArrayList<>(3)).addAll(entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public <K, T extends JsonAssetWithMap<K, M>, M extends AssetMap<K, T>> boolean containsAsset(Class<T> tClass, K key) {
|
||||
if (this.containedAssets != null) {
|
||||
List<T> assets = (List<T>)this.containedAssets.get(tClass);
|
||||
if (assets != null) {
|
||||
Function<T, K> keyFunction = AssetRegistry.<K, T, M>getAssetStore(tClass).getKeyFunction();
|
||||
|
||||
for (T asset : assets) {
|
||||
if (key.equals(keyFunction.apply(asset))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.containedRawAssets != null) {
|
||||
List<RawAsset<T>> rawAssets = (List<RawAsset<T>>)this.containedRawAssets.get(tClass);
|
||||
if (rawAssets != null) {
|
||||
for (RawAsset<T> rawAsset : rawAssets) {
|
||||
if (key.equals(rawAsset.getKey())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void loadContainedAssets(boolean reloading) {
|
||||
if (this.containedAssets != null) {
|
||||
for (Entry<Class<? extends JsonAssetWithMap>, List<Object>> entry : this.containedAssets.entrySet()) {
|
||||
AssetRegistry.getAssetStore(entry.getKey()).loadAssets("Hytale:Hytale", entry.getValue(), AssetUpdateQuery.DEFAULT, reloading);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.containedRawAssets != null) {
|
||||
for (Entry<Class<? extends JsonAssetWithMap>, List<RawAsset<Object>>> entry : this.containedRawAssets.entrySet()) {
|
||||
AssetRegistry.getAssetStore(entry.getKey()).loadBuffersWithKeys("Hytale:Hytale", entry.getValue(), AssetUpdateQuery.DEFAULT, reloading);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private IntSet ensureTag(@Nonnull String tag) {
|
||||
int idx = AssetRegistry.getOrCreateTagIndex(tag);
|
||||
this.expandedTagStorage.add(idx);
|
||||
return this.tagStorage.computeIfAbsent(idx, k -> {
|
||||
IntSet set = new IntOpenHashSet(3);
|
||||
this.unmodifiableTagStorage.put(k, IntSets.unmodifiable(set));
|
||||
return set;
|
||||
});
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Data{containedAssets="
|
||||
+ this.containedRawAssets
|
||||
+ ", rawTags="
|
||||
+ this.rawTags
|
||||
+ ", parent="
|
||||
+ this.containerData
|
||||
+ ", assetClass="
|
||||
+ this.assetClass
|
||||
+ ", key="
|
||||
+ this.key
|
||||
+ "}";
|
||||
}
|
||||
}
|
||||
}
|
||||
4
src/com/hypixel/hytale/assetstore/AssetHolder.java
Normal file
4
src/com/hypixel/hytale/assetstore/AssetHolder.java
Normal file
@@ -0,0 +1,4 @@
|
||||
package com.hypixel.hytale.assetstore;
|
||||
|
||||
public interface AssetHolder<K> {
|
||||
}
|
||||
30
src/com/hypixel/hytale/assetstore/AssetKeyValidator.java
Normal file
30
src/com/hypixel/hytale/assetstore/AssetKeyValidator.java
Normal file
@@ -0,0 +1,30 @@
|
||||
package com.hypixel.hytale.assetstore;
|
||||
|
||||
import com.hypixel.hytale.codec.schema.SchemaContext;
|
||||
import com.hypixel.hytale.codec.schema.config.Schema;
|
||||
import com.hypixel.hytale.codec.validation.ValidationResults;
|
||||
import com.hypixel.hytale.codec.validation.Validator;
|
||||
import java.util.function.Supplier;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class AssetKeyValidator<K> implements Validator<K> {
|
||||
private final Supplier<AssetStore<K, ?, ?>> store;
|
||||
|
||||
public AssetKeyValidator(Supplier<AssetStore<K, ?, ?>> store) {
|
||||
this.store = store;
|
||||
}
|
||||
|
||||
public AssetStore<K, ?, ?> getStore() {
|
||||
return this.store.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(K k, @Nonnull ValidationResults results) {
|
||||
this.store.get().validate(k, results, results.getExtraInfo());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateSchema(SchemaContext context, @Nonnull Schema target) {
|
||||
target.setHytaleAssetRef(this.store.get().getAssetClass().getSimpleName());
|
||||
}
|
||||
}
|
||||
58
src/com/hypixel/hytale/assetstore/AssetLoadResult.java
Normal file
58
src/com/hypixel/hytale/assetstore/AssetLoadResult.java
Normal file
@@ -0,0 +1,58 @@
|
||||
package com.hypixel.hytale.assetstore;
|
||||
|
||||
import com.hypixel.hytale.assetstore.map.JsonAssetWithMap;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class AssetLoadResult<K, T> {
|
||||
private final Map<K, T> loadedAssets;
|
||||
private final Map<K, Path> loadedKeyToPathMap;
|
||||
private final Set<K> failedToLoadKeys;
|
||||
private final Set<Path> failedToLoadPaths;
|
||||
private final Map<Class<? extends JsonAssetWithMap>, AssetLoadResult> childAssetResults;
|
||||
|
||||
public AssetLoadResult(
|
||||
Map<K, T> loadedAssets,
|
||||
Map<K, Path> loadedKeyToPathMap,
|
||||
Set<K> failedToLoadKeys,
|
||||
Set<Path> failedToLoadPaths,
|
||||
Map<Class<? extends JsonAssetWithMap>, AssetLoadResult> childAssetResults
|
||||
) {
|
||||
this.loadedAssets = loadedAssets;
|
||||
this.loadedKeyToPathMap = loadedKeyToPathMap;
|
||||
this.failedToLoadKeys = failedToLoadKeys;
|
||||
this.failedToLoadPaths = failedToLoadPaths;
|
||||
this.childAssetResults = childAssetResults;
|
||||
}
|
||||
|
||||
public Map<K, T> getLoadedAssets() {
|
||||
return this.loadedAssets;
|
||||
}
|
||||
|
||||
public Map<K, Path> getLoadedKeyToPathMap() {
|
||||
return this.loadedKeyToPathMap;
|
||||
}
|
||||
|
||||
public Set<K> getFailedToLoadKeys() {
|
||||
return this.failedToLoadKeys;
|
||||
}
|
||||
|
||||
public Set<Path> getFailedToLoadPaths() {
|
||||
return this.failedToLoadPaths;
|
||||
}
|
||||
|
||||
public boolean hasFailed() {
|
||||
if (this.failedToLoadKeys.isEmpty() && this.failedToLoadPaths.isEmpty()) {
|
||||
for (AssetLoadResult result : this.childAssetResults.values()) {
|
||||
if (result.hasFailed()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
58
src/com/hypixel/hytale/assetstore/AssetMap.java
Normal file
58
src/com/hypixel/hytale/assetstore/AssetMap.java
Normal file
@@ -0,0 +1,58 @@
|
||||
package com.hypixel.hytale.assetstore;
|
||||
|
||||
import com.hypixel.hytale.assetstore.codec.AssetCodec;
|
||||
import it.unimi.dsi.fastutil.ints.IntSet;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Map.Entry;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public abstract class AssetMap<K, T extends JsonAsset<K>> {
|
||||
public AssetMap() {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public abstract T getAsset(K var1);
|
||||
|
||||
@Nullable
|
||||
public abstract T getAsset(@Nonnull String var1, K var2);
|
||||
|
||||
@Nullable
|
||||
public abstract Path getPath(K var1);
|
||||
|
||||
@Nullable
|
||||
public abstract String getAssetPack(K var1);
|
||||
|
||||
public abstract Set<K> getKeys(Path var1);
|
||||
|
||||
public abstract Set<K> getChildren(K var1);
|
||||
|
||||
public abstract int getAssetCount();
|
||||
|
||||
public abstract Map<K, T> getAssetMap();
|
||||
|
||||
public abstract Map<K, Path> getPathMap(@Nonnull String var1);
|
||||
|
||||
public abstract Set<K> getKeysForTag(int var1);
|
||||
|
||||
public abstract IntSet getTagIndexes();
|
||||
|
||||
public abstract int getTagCount();
|
||||
|
||||
protected abstract void clear();
|
||||
|
||||
protected abstract void putAll(@Nonnull String var1, AssetCodec<K, T> var2, Map<K, T> var3, Map<K, Path> var4, Map<K, Set<K>> var5);
|
||||
|
||||
protected abstract Set<K> remove(Set<K> var1);
|
||||
|
||||
protected abstract Set<K> remove(@Nonnull String var1, Set<K> var2, List<Entry<String, Object>> var3);
|
||||
|
||||
public boolean requireReplaceOnRemove() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public abstract Set<K> getKeysForPack(@Nonnull String var1);
|
||||
}
|
||||
79
src/com/hypixel/hytale/assetstore/AssetPack.java
Normal file
79
src/com/hypixel/hytale/assetstore/AssetPack.java
Normal file
@@ -0,0 +1,79 @@
|
||||
package com.hypixel.hytale.assetstore;
|
||||
|
||||
import com.hypixel.hytale.common.plugin.PluginManifest;
|
||||
import java.nio.file.FileSystem;
|
||||
import java.nio.file.Path;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class AssetPack {
|
||||
@Nonnull
|
||||
private final String name;
|
||||
@Nonnull
|
||||
private final Path root;
|
||||
@Nullable
|
||||
private final FileSystem fileSystem;
|
||||
private final boolean isImmutable;
|
||||
private final PluginManifest manifest;
|
||||
private final Path packLocation;
|
||||
|
||||
public AssetPack(Path packLocation, @Nonnull String name, @Nonnull Path root, @Nullable FileSystem fileSystem, boolean isImmutable, PluginManifest manifest) {
|
||||
this.name = name;
|
||||
this.root = root;
|
||||
this.fileSystem = fileSystem;
|
||||
this.isImmutable = isImmutable;
|
||||
this.manifest = manifest;
|
||||
this.packLocation = packLocation;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public Path getRoot() {
|
||||
return this.root;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public FileSystem getFileSystem() {
|
||||
return this.fileSystem;
|
||||
}
|
||||
|
||||
public PluginManifest getManifest() {
|
||||
return this.manifest;
|
||||
}
|
||||
|
||||
public boolean isImmutable() {
|
||||
return this.isImmutable;
|
||||
}
|
||||
|
||||
public Path getPackLocation() {
|
||||
return this.packLocation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
} else if (o != null && this.getClass() == o.getClass()) {
|
||||
AssetPack assetPack = (AssetPack)o;
|
||||
return !this.name.equals(assetPack.name) ? false : this.root.equals(assetPack.root);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = this.name.hashCode();
|
||||
return 31 * result + this.root.hashCode();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public String toString() {
|
||||
return "AssetPack{name='" + this.name + "', root=" + this.root + ", fileSystem=" + this.fileSystem + "}";
|
||||
}
|
||||
}
|
||||
39
src/com/hypixel/hytale/assetstore/AssetReferences.java
Normal file
39
src/com/hypixel/hytale/assetstore/AssetReferences.java
Normal file
@@ -0,0 +1,39 @@
|
||||
package com.hypixel.hytale.assetstore;
|
||||
|
||||
import com.hypixel.hytale.assetstore.map.JsonAssetWithMap;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class AssetReferences<CK, C extends JsonAssetWithMap<CK, ?>> {
|
||||
private final Class<C> parentAssetClass;
|
||||
private final Set<CK> parentKeys;
|
||||
|
||||
public AssetReferences(Class<C> parentAssetClass, Set<CK> parentKeys) {
|
||||
this.parentAssetClass = parentAssetClass;
|
||||
this.parentKeys = parentKeys;
|
||||
}
|
||||
|
||||
public Class<C> getParentAssetClass() {
|
||||
return this.parentAssetClass;
|
||||
}
|
||||
|
||||
public Set<CK> getParentKeys() {
|
||||
return this.parentKeys;
|
||||
}
|
||||
|
||||
public <T extends JsonAssetWithMap<K, ?>, K> void addChildAssetReferences(Class<T> tClass, K childKey) {
|
||||
Class parentAssetClass = this.parentAssetClass;
|
||||
AssetStore<CK, C, ?> assetStore = AssetRegistry.getAssetStore(parentAssetClass);
|
||||
|
||||
for (CK parentKey : this.parentKeys) {
|
||||
assetStore.addChildAssetReferences(parentKey, tClass, Collections.singleton(childKey));
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public String toString() {
|
||||
return "AssetReferences{parentAssetClass=" + this.parentAssetClass + ", parentKeys=" + this.parentKeys + "}";
|
||||
}
|
||||
}
|
||||
145
src/com/hypixel/hytale/assetstore/AssetRegistry.java
Normal file
145
src/com/hypixel/hytale/assetstore/AssetRegistry.java
Normal file
@@ -0,0 +1,145 @@
|
||||
package com.hypixel.hytale.assetstore;
|
||||
|
||||
import com.hypixel.hytale.assetstore.event.RegisterAssetStoreEvent;
|
||||
import com.hypixel.hytale.assetstore.event.RemoveAssetStoreEvent;
|
||||
import com.hypixel.hytale.assetstore.map.JsonAssetWithMap;
|
||||
import com.hypixel.hytale.event.IEventDispatcher;
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.locks.ReadWriteLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
import java.util.concurrent.locks.StampedLock;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class AssetRegistry {
|
||||
public static final ReadWriteLock ASSET_LOCK = new ReentrantReadWriteLock();
|
||||
public static boolean HAS_INIT = false;
|
||||
public static final int TAG_NOT_FOUND = Integer.MIN_VALUE;
|
||||
private static final Map<Class<? extends JsonAssetWithMap>, AssetStore<?, ?, ?>> storeMap = new HashMap<>();
|
||||
private static final Map<Class<? extends JsonAssetWithMap>, AssetStore<?, ?, ?>> storeMapUnmodifiable = Collections.unmodifiableMap(storeMap);
|
||||
private static final AtomicInteger NEXT_TAG_INDEX = new AtomicInteger();
|
||||
private static final StampedLock TAG_LOCK = new StampedLock();
|
||||
private static final Object2IntMap<String> TAG_MAP = new Object2IntOpenHashMap<>();
|
||||
private static final Object2IntMap<String> CLIENT_TAG_MAP = new Object2IntOpenHashMap<>();
|
||||
|
||||
public AssetRegistry() {
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static Map<Class<? extends JsonAssetWithMap>, AssetStore<?, ?, ?>> getStoreMap() {
|
||||
return storeMapUnmodifiable;
|
||||
}
|
||||
|
||||
public static <K, T extends JsonAssetWithMap<K, M>, M extends AssetMap<K, T>> AssetStore<K, T, M> getAssetStore(Class<T> tClass) {
|
||||
return (AssetStore<K, T, M>)storeMap.get(tClass);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static <K, T extends JsonAssetWithMap<K, M>, M extends AssetMap<K, T>, S extends AssetStore<K, T, M>> S register(@Nonnull S assetStore) {
|
||||
ASSET_LOCK.writeLock().lock();
|
||||
|
||||
try {
|
||||
if (storeMap.putIfAbsent(assetStore.getAssetClass(), assetStore) != null) {
|
||||
throw new IllegalArgumentException("Asset Store already exists for " + assetStore.getAssetClass());
|
||||
}
|
||||
} finally {
|
||||
ASSET_LOCK.writeLock().unlock();
|
||||
}
|
||||
|
||||
IEventDispatcher<RegisterAssetStoreEvent, RegisterAssetStoreEvent> dispatch = assetStore.getEventBus().dispatchFor(RegisterAssetStoreEvent.class);
|
||||
if (dispatch.hasListener()) {
|
||||
dispatch.dispatch(new RegisterAssetStoreEvent(assetStore));
|
||||
}
|
||||
|
||||
return assetStore;
|
||||
}
|
||||
|
||||
public static <K, T extends JsonAssetWithMap<K, M>, M extends AssetMap<K, T>, S extends AssetStore<K, T, M>> void unregister(@Nonnull S assetStore) {
|
||||
ASSET_LOCK.writeLock().lock();
|
||||
|
||||
try {
|
||||
storeMap.remove(assetStore.getAssetClass());
|
||||
} finally {
|
||||
ASSET_LOCK.writeLock().unlock();
|
||||
}
|
||||
|
||||
IEventDispatcher<RemoveAssetStoreEvent, RemoveAssetStoreEvent> dispatch = assetStore.getEventBus().dispatchFor(RemoveAssetStoreEvent.class);
|
||||
if (dispatch.hasListener()) {
|
||||
dispatch.dispatch(new RemoveAssetStoreEvent(assetStore));
|
||||
}
|
||||
}
|
||||
|
||||
public static int getTagIndex(@Nonnull String tag) {
|
||||
if (tag == null) {
|
||||
throw new IllegalArgumentException("tag can't be null!");
|
||||
} else {
|
||||
long stamp = TAG_LOCK.readLock();
|
||||
|
||||
int var3;
|
||||
try {
|
||||
var3 = TAG_MAP.getInt(tag);
|
||||
} finally {
|
||||
TAG_LOCK.unlockRead(stamp);
|
||||
}
|
||||
|
||||
return var3;
|
||||
}
|
||||
}
|
||||
|
||||
public static int getOrCreateTagIndex(@Nonnull String tag) {
|
||||
if (tag == null) {
|
||||
throw new IllegalArgumentException("tag can't be null!");
|
||||
} else {
|
||||
long stamp = TAG_LOCK.writeLock();
|
||||
|
||||
int var3;
|
||||
try {
|
||||
var3 = TAG_MAP.computeIfAbsent(tag.intern(), k -> NEXT_TAG_INDEX.getAndIncrement());
|
||||
} finally {
|
||||
TAG_LOCK.unlockWrite(stamp);
|
||||
}
|
||||
|
||||
return var3;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean registerClientTag(@Nonnull String tag) {
|
||||
if (tag == null) {
|
||||
throw new IllegalArgumentException("tag can't be null!");
|
||||
} else {
|
||||
long stamp = TAG_LOCK.writeLock();
|
||||
|
||||
boolean var3;
|
||||
try {
|
||||
var3 = CLIENT_TAG_MAP.put(tag, TAG_MAP.computeIfAbsent(tag, k -> NEXT_TAG_INDEX.getAndIncrement())) == Integer.MIN_VALUE;
|
||||
} finally {
|
||||
TAG_LOCK.unlockWrite(stamp);
|
||||
}
|
||||
|
||||
return var3;
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static Object2IntMap<String> getClientTags() {
|
||||
long stamp = TAG_LOCK.readLock();
|
||||
|
||||
Object2IntOpenHashMap var2;
|
||||
try {
|
||||
var2 = new Object2IntOpenHashMap<>(CLIENT_TAG_MAP);
|
||||
} finally {
|
||||
TAG_LOCK.unlockRead(stamp);
|
||||
}
|
||||
|
||||
return var2;
|
||||
}
|
||||
|
||||
static {
|
||||
TAG_MAP.defaultReturnValue(Integer.MIN_VALUE);
|
||||
CLIENT_TAG_MAP.defaultReturnValue(Integer.MIN_VALUE);
|
||||
}
|
||||
}
|
||||
1761
src/com/hypixel/hytale/assetstore/AssetStore.java
Normal file
1761
src/com/hypixel/hytale/assetstore/AssetStore.java
Normal file
File diff suppressed because it is too large
Load Diff
178
src/com/hypixel/hytale/assetstore/AssetUpdateQuery.java
Normal file
178
src/com/hypixel/hytale/assetstore/AssetUpdateQuery.java
Normal file
@@ -0,0 +1,178 @@
|
||||
package com.hypixel.hytale.assetstore;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class AssetUpdateQuery {
|
||||
public static final AssetUpdateQuery DEFAULT = new AssetUpdateQuery(AssetUpdateQuery.RebuildCache.DEFAULT);
|
||||
public static final AssetUpdateQuery DEFAULT_NO_REBUILD = new AssetUpdateQuery(AssetUpdateQuery.RebuildCache.NO_REBUILD);
|
||||
private final boolean disableAssetCompare;
|
||||
private final AssetUpdateQuery.RebuildCache rebuildCache;
|
||||
|
||||
public AssetUpdateQuery(boolean disableAssetCompare, AssetUpdateQuery.RebuildCache rebuildCache) {
|
||||
this.disableAssetCompare = disableAssetCompare;
|
||||
this.rebuildCache = rebuildCache;
|
||||
}
|
||||
|
||||
public AssetUpdateQuery(AssetUpdateQuery.RebuildCache rebuildCache) {
|
||||
this(AssetStore.DISABLE_ASSET_COMPARE, rebuildCache);
|
||||
}
|
||||
|
||||
public boolean isDisableAssetCompare() {
|
||||
return this.disableAssetCompare;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public AssetUpdateQuery.RebuildCache getRebuildCache() {
|
||||
return this.rebuildCache;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public String toString() {
|
||||
return "AssetUpdateQuery{rebuildCache=" + this.rebuildCache + "}";
|
||||
}
|
||||
|
||||
public static class RebuildCache {
|
||||
public static final AssetUpdateQuery.RebuildCache DEFAULT = new AssetUpdateQuery.RebuildCache(true, true, true, true, true, true);
|
||||
public static final AssetUpdateQuery.RebuildCache NO_REBUILD = new AssetUpdateQuery.RebuildCache(false, false, false, false, false, false);
|
||||
private final boolean blockTextures;
|
||||
private final boolean models;
|
||||
private final boolean modelTextures;
|
||||
private final boolean mapGeometry;
|
||||
private final boolean itemIcons;
|
||||
private final boolean commonAssetsRebuild;
|
||||
|
||||
public RebuildCache(boolean blockTextures, boolean models, boolean modelTextures, boolean mapGeometry, boolean itemIcons, boolean commonAssetsRebuild) {
|
||||
this.blockTextures = blockTextures;
|
||||
this.models = models;
|
||||
this.modelTextures = modelTextures;
|
||||
this.mapGeometry = mapGeometry;
|
||||
this.itemIcons = itemIcons;
|
||||
this.commonAssetsRebuild = commonAssetsRebuild;
|
||||
}
|
||||
|
||||
public boolean isBlockTextures() {
|
||||
return this.blockTextures;
|
||||
}
|
||||
|
||||
public boolean isModels() {
|
||||
return this.models;
|
||||
}
|
||||
|
||||
public boolean isModelTextures() {
|
||||
return this.modelTextures;
|
||||
}
|
||||
|
||||
public boolean isMapGeometry() {
|
||||
return this.mapGeometry;
|
||||
}
|
||||
|
||||
public boolean isItemIcons() {
|
||||
return this.itemIcons;
|
||||
}
|
||||
|
||||
public boolean isCommonAssetsRebuild() {
|
||||
return this.commonAssetsRebuild;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public AssetUpdateQuery.RebuildCacheBuilder toBuilder() {
|
||||
return new AssetUpdateQuery.RebuildCacheBuilder(
|
||||
this.blockTextures, this.models, this.modelTextures, this.mapGeometry, this.itemIcons, this.commonAssetsRebuild
|
||||
);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static AssetUpdateQuery.RebuildCacheBuilder builder() {
|
||||
return new AssetUpdateQuery.RebuildCacheBuilder();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RebuildCache{blockTextures="
|
||||
+ this.blockTextures
|
||||
+ ", models="
|
||||
+ this.models
|
||||
+ ", modelTextures="
|
||||
+ this.modelTextures
|
||||
+ ", mapGeometry="
|
||||
+ this.mapGeometry
|
||||
+ ", icons="
|
||||
+ this.itemIcons
|
||||
+ ", commonAssetsRebuild="
|
||||
+ this.commonAssetsRebuild
|
||||
+ "}";
|
||||
}
|
||||
}
|
||||
|
||||
public static class RebuildCacheBuilder {
|
||||
private boolean blockTextures;
|
||||
private boolean models;
|
||||
private boolean modelTextures;
|
||||
private boolean mapGeometry;
|
||||
private boolean itemIcons;
|
||||
private boolean commonAssetsRebuild;
|
||||
|
||||
RebuildCacheBuilder() {
|
||||
}
|
||||
|
||||
RebuildCacheBuilder(boolean blockTextures, boolean models, boolean modelTextures, boolean mapGeometry, boolean itemIcons, boolean commonAssetsRebuild) {
|
||||
this.blockTextures = blockTextures;
|
||||
this.models = models;
|
||||
this.modelTextures = modelTextures;
|
||||
this.mapGeometry = mapGeometry;
|
||||
this.itemIcons = itemIcons;
|
||||
this.commonAssetsRebuild = commonAssetsRebuild;
|
||||
}
|
||||
|
||||
public void setBlockTextures(boolean blockTextures) {
|
||||
this.blockTextures = blockTextures;
|
||||
}
|
||||
|
||||
public void setModels(boolean models) {
|
||||
this.models = models;
|
||||
}
|
||||
|
||||
public void setModelTextures(boolean modelTextures) {
|
||||
this.modelTextures = modelTextures;
|
||||
}
|
||||
|
||||
public void setMapGeometry(boolean mapGeometry) {
|
||||
this.mapGeometry = mapGeometry;
|
||||
}
|
||||
|
||||
public void setItemIcons(boolean itemIcons) {
|
||||
this.itemIcons = itemIcons;
|
||||
}
|
||||
|
||||
public void setCommonAssetsRebuild(boolean commonAssetsRebuild) {
|
||||
this.commonAssetsRebuild = commonAssetsRebuild;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public AssetUpdateQuery.RebuildCache build() {
|
||||
return new AssetUpdateQuery.RebuildCache(
|
||||
this.blockTextures, this.models, this.modelTextures, this.mapGeometry, this.itemIcons, this.commonAssetsRebuild
|
||||
);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RebuildCache{blockTextures="
|
||||
+ this.blockTextures
|
||||
+ ", models="
|
||||
+ this.models
|
||||
+ ", modelTextures="
|
||||
+ this.modelTextures
|
||||
+ ", mapGeometry="
|
||||
+ this.mapGeometry
|
||||
+ ", icons="
|
||||
+ this.itemIcons
|
||||
+ ", commonAssetsRebuild="
|
||||
+ this.commonAssetsRebuild
|
||||
+ "}";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package com.hypixel.hytale.assetstore;
|
||||
|
||||
import com.hypixel.hytale.codec.ExtraInfo;
|
||||
import com.hypixel.hytale.codec.validation.ValidationResults;
|
||||
import com.hypixel.hytale.logger.HytaleLogger;
|
||||
import com.hypixel.hytale.logger.backend.HytaleLoggerBackend;
|
||||
import com.hypixel.hytale.logger.util.GithubMessageUtil;
|
||||
import java.nio.file.Path;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import org.checkerframework.checker.nullness.compatqual.NonNullDecl;
|
||||
|
||||
public class AssetValidationResults extends ValidationResults {
|
||||
private Set<Class<? extends JsonAsset>> disabledMissingAssetClasses;
|
||||
|
||||
public AssetValidationResults(ExtraInfo extraInfo) {
|
||||
super(extraInfo);
|
||||
}
|
||||
|
||||
public void handleMissingAsset(String field, @Nonnull Class<? extends JsonAsset> assetType, Object assetId) {
|
||||
if (this.disabledMissingAssetClasses == null || !this.disabledMissingAssetClasses.contains(assetType)) {
|
||||
throw new MissingAssetException(field, assetType, assetId);
|
||||
}
|
||||
}
|
||||
|
||||
public void handleMissingAsset(String field, @Nonnull Class<? extends JsonAsset> assetType, Object assetId, String extra) {
|
||||
if (this.disabledMissingAssetClasses == null || !this.disabledMissingAssetClasses.contains(assetType)) {
|
||||
throw new MissingAssetException(field, assetType, assetId, extra);
|
||||
}
|
||||
}
|
||||
|
||||
public void disableMissingAssetFor(Class<? extends JsonAsset> assetType) {
|
||||
if (this.disabledMissingAssetClasses == null) {
|
||||
this.disabledMissingAssetClasses = new HashSet<>();
|
||||
}
|
||||
|
||||
this.disabledMissingAssetClasses.add(assetType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logOrThrowValidatorExceptions(@NonNullDecl HytaleLogger logger, @NonNullDecl String msg) {
|
||||
this.logOrThrowValidatorExceptions(logger, msg, null, 0);
|
||||
}
|
||||
|
||||
public void logOrThrowValidatorExceptions(@NonNullDecl HytaleLogger logger, @NonNullDecl String msg, @Nullable Path path, int lineOffset) {
|
||||
if (GithubMessageUtil.isGithub() && this.validatorExceptions != null && !this.validatorExceptions.isEmpty()) {
|
||||
for (ValidationResults.ValidatorResultsHolder holder : this.validatorExceptions) {
|
||||
String file = "unknown";
|
||||
if (path == null && this.extraInfo instanceof AssetExtraInfo<?> assetExtraInfo) {
|
||||
path = assetExtraInfo.getAssetPath();
|
||||
}
|
||||
|
||||
if (path != null) {
|
||||
file = path.toString();
|
||||
}
|
||||
|
||||
for (ValidationResults.ValidationResult result : holder.results()) {
|
||||
HytaleLoggerBackend.rawLog(
|
||||
switch (result.result()) {
|
||||
case SUCCESS -> "";
|
||||
case WARNING -> holder.line() == -1
|
||||
? GithubMessageUtil.messageWarning(file, result.reason())
|
||||
: GithubMessageUtil.messageWarning(file, holder.line() + lineOffset, holder.column(), result.reason());
|
||||
case FAIL -> holder.line() == -1
|
||||
? GithubMessageUtil.messageError(file, result.reason())
|
||||
: GithubMessageUtil.messageError(file, holder.line() + lineOffset, holder.column(), result.reason());
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
super.logOrThrowValidatorExceptions(logger, msg);
|
||||
}
|
||||
}
|
||||
50
src/com/hypixel/hytale/assetstore/DecodedAsset.java
Normal file
50
src/com/hypixel/hytale/assetstore/DecodedAsset.java
Normal file
@@ -0,0 +1,50 @@
|
||||
package com.hypixel.hytale.assetstore;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class DecodedAsset<K, T extends JsonAsset<K>> implements AssetHolder<K> {
|
||||
private final K key;
|
||||
private final T asset;
|
||||
|
||||
public DecodedAsset(K key, T asset) {
|
||||
this.key = key;
|
||||
this.asset = asset;
|
||||
}
|
||||
|
||||
public K getKey() {
|
||||
return this.key;
|
||||
}
|
||||
|
||||
public T getAsset() {
|
||||
return this.asset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
} else if (o != null && this.getClass() == o.getClass()) {
|
||||
DecodedAsset<?, ?> that = (DecodedAsset<?, ?>)o;
|
||||
if (this.key != null ? this.key.equals(that.key) : that.key == null) {
|
||||
return this.asset != null ? this.asset.equals(that.asset) : that.asset == null;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = this.key != null ? this.key.hashCode() : 0;
|
||||
return 31 * result + (this.asset != null ? this.asset.hashCode() : 0);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DecodedAsset{key=" + this.key + ", asset=" + this.asset + "}";
|
||||
}
|
||||
}
|
||||
5
src/com/hypixel/hytale/assetstore/JsonAsset.java
Normal file
5
src/com/hypixel/hytale/assetstore/JsonAsset.java
Normal file
@@ -0,0 +1,5 @@
|
||||
package com.hypixel.hytale.assetstore;
|
||||
|
||||
public interface JsonAsset<K> {
|
||||
K getId();
|
||||
}
|
||||
55
src/com/hypixel/hytale/assetstore/MissingAssetException.java
Normal file
55
src/com/hypixel/hytale/assetstore/MissingAssetException.java
Normal file
@@ -0,0 +1,55 @@
|
||||
package com.hypixel.hytale.assetstore;
|
||||
|
||||
import com.hypixel.hytale.codec.ExtraInfo;
|
||||
import com.hypixel.hytale.codec.validation.ValidationResults;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class MissingAssetException extends RuntimeException {
|
||||
private String field;
|
||||
private Class<? extends JsonAsset> assetType;
|
||||
private Object assetId;
|
||||
|
||||
public MissingAssetException(String field, @Nonnull Class<? extends JsonAsset> assetType, Object assetId) {
|
||||
super("Missing asset '" + assetId + "' of type " + assetType.getSimpleName() + " for field '" + field + "'!");
|
||||
this.field = field;
|
||||
this.assetType = assetType;
|
||||
this.assetId = assetId;
|
||||
}
|
||||
|
||||
public MissingAssetException(String field, @Nonnull Class<? extends JsonAsset> assetType, Object assetId, String extra) {
|
||||
super("Missing asset '" + assetId + "' of type " + assetType.getSimpleName() + " for field '" + field + "'! " + extra);
|
||||
this.field = field;
|
||||
this.assetType = assetType;
|
||||
this.assetId = assetId;
|
||||
}
|
||||
|
||||
public String getField() {
|
||||
return this.field;
|
||||
}
|
||||
|
||||
public Class<? extends JsonAsset> getAssetType() {
|
||||
return this.assetType;
|
||||
}
|
||||
|
||||
public Object getAssetId() {
|
||||
return this.assetId;
|
||||
}
|
||||
|
||||
public static void handle(@Nonnull ExtraInfo extraInfo, String field, @Nonnull Class<? extends JsonAsset> assetType, Object assetId) {
|
||||
ValidationResults validationResults = extraInfo.getValidationResults();
|
||||
if (validationResults instanceof AssetValidationResults) {
|
||||
((AssetValidationResults)validationResults).handleMissingAsset(field, assetType, assetId);
|
||||
} else {
|
||||
throw new MissingAssetException(field, assetType, assetId);
|
||||
}
|
||||
}
|
||||
|
||||
public static void handle(@Nonnull ExtraInfo extraInfo, String field, @Nonnull Class<? extends JsonAsset> assetType, Object assetId, String extra) {
|
||||
ValidationResults validationResults = extraInfo.getValidationResults();
|
||||
if (validationResults instanceof AssetValidationResults) {
|
||||
((AssetValidationResults)validationResults).handleMissingAsset(field, assetType, assetId, extra);
|
||||
} else {
|
||||
throw new MissingAssetException(field, assetType, assetId, extra);
|
||||
}
|
||||
}
|
||||
}
|
||||
153
src/com/hypixel/hytale/assetstore/RawAsset.java
Normal file
153
src/com/hypixel/hytale/assetstore/RawAsset.java
Normal file
@@ -0,0 +1,153 @@
|
||||
package com.hypixel.hytale.assetstore;
|
||||
|
||||
import com.hypixel.hytale.assetstore.codec.ContainedAssetCodec;
|
||||
import com.hypixel.hytale.assetstore.map.JsonAssetWithMap;
|
||||
import com.hypixel.hytale.codec.util.RawJsonReader;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.function.Supplier;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.ParametersAreNullableByDefault;
|
||||
|
||||
@ParametersAreNullableByDefault
|
||||
public class RawAsset<K> implements AssetHolder<K> {
|
||||
private final Path parentPath;
|
||||
@Nullable
|
||||
private final K key;
|
||||
private final int lineOffset;
|
||||
private final boolean parentKeyResolved;
|
||||
@Nullable
|
||||
private final K parentKey;
|
||||
@Nullable
|
||||
private final Path path;
|
||||
@Nullable
|
||||
private final char[] buffer;
|
||||
@Nullable
|
||||
private final AssetExtraInfo.Data containerData;
|
||||
@Nonnull
|
||||
private final ContainedAssetCodec.Mode containedAssetMode;
|
||||
|
||||
public RawAsset(K key, Path path) {
|
||||
this.key = key;
|
||||
this.lineOffset = 0;
|
||||
this.parentKeyResolved = false;
|
||||
this.parentKey = null;
|
||||
this.path = path;
|
||||
this.parentPath = null;
|
||||
this.buffer = null;
|
||||
this.containerData = null;
|
||||
this.containedAssetMode = ContainedAssetCodec.Mode.NONE;
|
||||
}
|
||||
|
||||
public RawAsset(
|
||||
Path parentPath,
|
||||
K key,
|
||||
K parentKey,
|
||||
int lineOffset,
|
||||
char[] buffer,
|
||||
AssetExtraInfo.Data containerData,
|
||||
@Nonnull ContainedAssetCodec.Mode containedAssetMode
|
||||
) {
|
||||
this.key = key;
|
||||
this.lineOffset = lineOffset;
|
||||
this.parentKeyResolved = true;
|
||||
this.parentKey = parentKey;
|
||||
this.path = null;
|
||||
this.parentPath = parentPath;
|
||||
this.buffer = buffer;
|
||||
this.containerData = containerData;
|
||||
this.containedAssetMode = containedAssetMode;
|
||||
}
|
||||
|
||||
private RawAsset(
|
||||
K key,
|
||||
boolean parentKeyResolved,
|
||||
K parentKey,
|
||||
Path path,
|
||||
char[] buffer,
|
||||
AssetExtraInfo.Data containerData,
|
||||
@Nonnull ContainedAssetCodec.Mode containedAssetMode
|
||||
) {
|
||||
this.key = key;
|
||||
this.lineOffset = 0;
|
||||
this.parentKeyResolved = parentKeyResolved;
|
||||
this.parentKey = parentKey;
|
||||
this.path = path;
|
||||
this.parentPath = null;
|
||||
this.buffer = buffer;
|
||||
this.containerData = containerData;
|
||||
this.containedAssetMode = containedAssetMode;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public K getKey() {
|
||||
return this.key;
|
||||
}
|
||||
|
||||
public boolean isParentKeyResolved() {
|
||||
return this.parentKeyResolved;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public K getParentKey() {
|
||||
return this.parentKey;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Path getPath() {
|
||||
return this.path;
|
||||
}
|
||||
|
||||
public Path getParentPath() {
|
||||
return this.parentPath;
|
||||
}
|
||||
|
||||
public int getLineOffset() {
|
||||
return this.lineOffset;
|
||||
}
|
||||
|
||||
public char[] getBuffer() {
|
||||
return this.buffer;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public ContainedAssetCodec.Mode getContainedAssetMode() {
|
||||
return this.containedAssetMode;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public RawJsonReader toRawJsonReader(@Nonnull Supplier<char[]> bufferSupplier) throws IOException {
|
||||
return this.path != null ? RawJsonReader.fromPath(this.path, bufferSupplier.get()) : RawJsonReader.fromBuffer(this.buffer);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public AssetExtraInfo.Data makeData(Class<? extends JsonAssetWithMap<K, ?>> aClass, K key, K parentKey) {
|
||||
boolean inheritTags = switch (this.containedAssetMode) {
|
||||
case INHERIT_ID, INHERIT_ID_AND_PARENT, INJECT_PARENT -> true;
|
||||
case NONE, GENERATE_ID -> false;
|
||||
};
|
||||
return new AssetExtraInfo.Data(this.containerData, aClass, key, parentKey, inheritTags);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public RawAsset<K> withResolveKeys(K key, K parentKey) {
|
||||
return new RawAsset<>(key, true, parentKey, this.path, this.buffer, this.containerData, this.containedAssetMode);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RawAsset{key="
|
||||
+ this.key
|
||||
+ ", parentKeyResolved="
|
||||
+ this.parentKeyResolved
|
||||
+ ", parentKey="
|
||||
+ this.parentKey
|
||||
+ ", path="
|
||||
+ this.path
|
||||
+ ", buffer.length="
|
||||
+ (this.buffer != null ? this.buffer.length : -1)
|
||||
+ "}";
|
||||
}
|
||||
}
|
||||
225
src/com/hypixel/hytale/assetstore/codec/AssetBuilderCodec.java
Normal file
225
src/com/hypixel/hytale/assetstore/codec/AssetBuilderCodec.java
Normal file
@@ -0,0 +1,225 @@
|
||||
package com.hypixel.hytale.assetstore.codec;
|
||||
|
||||
import com.hypixel.hytale.assetstore.AssetExtraInfo;
|
||||
import com.hypixel.hytale.assetstore.JsonAsset;
|
||||
import com.hypixel.hytale.codec.Codec;
|
||||
import com.hypixel.hytale.codec.KeyedCodec;
|
||||
import com.hypixel.hytale.codec.builder.BuilderCodec;
|
||||
import com.hypixel.hytale.codec.codecs.map.MapCodec;
|
||||
import com.hypixel.hytale.codec.schema.SchemaContext;
|
||||
import com.hypixel.hytale.codec.schema.config.ObjectSchema;
|
||||
import com.hypixel.hytale.codec.schema.config.Schema;
|
||||
import com.hypixel.hytale.codec.util.RawJsonReader;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class AssetBuilderCodec<K, T extends JsonAsset<K>> extends BuilderCodec<T> implements AssetCodec<K, T> {
|
||||
public static final KeyedCodec<Map<String, String[]>> TAGS_CODEC = new KeyedCodec<>("Tags", new MapCodec<>(Codec.STRING_ARRAY, HashMap::new));
|
||||
private static final String TAG_DOCUMENTATION = "Tags are a general way to describe an asset that can be interpreted by other systems in a way they see fit.\n\nFor example you could tag something with a **Material** tag with the values **Solid** and **Stone**, And another single tag **Ore**.\n\nTags will be expanded into a single list of tags automatically. Using the above example with **Material** and **Ore** the end result would be the following list of tags: **Ore**, **Material**, **Solid**, **Stone**, **Material=Solid** and **Material=Stone**.";
|
||||
@Nonnull
|
||||
protected final KeyedCodec<K> idCodec;
|
||||
@Nonnull
|
||||
protected final KeyedCodec<K> parentCodec;
|
||||
protected final BiConsumer<T, K> idSetter;
|
||||
protected final BiConsumer<T, AssetExtraInfo.Data> dataSetter;
|
||||
@Nonnull
|
||||
protected final Function<T, AssetExtraInfo.Data> dataGetter;
|
||||
|
||||
protected AssetBuilderCodec(@Nonnull AssetBuilderCodec.Builder<K, T> builder) {
|
||||
super(builder);
|
||||
this.idCodec = builder.idCodec;
|
||||
this.parentCodec = new KeyedCodec<>("Parent", this.idCodec.getChildCodec());
|
||||
this.idSetter = builder.idSetter;
|
||||
this.dataSetter = builder.dataSetter;
|
||||
this.dataGetter = builder.dataGetter;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public KeyedCodec<K> getKeyCodec() {
|
||||
return this.idCodec;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public KeyedCodec<K> getParentCodec() {
|
||||
return this.parentCodec;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AssetExtraInfo.Data getData(T t) {
|
||||
return this.dataGetter.apply(t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T decodeJsonAsset(@Nonnull RawJsonReader reader, @Nonnull AssetExtraInfo<K> extraInfo) throws IOException {
|
||||
return this.decodeAndInheritJsonAsset(reader, null, extraInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T decodeAndInheritJsonAsset(@Nonnull RawJsonReader reader, @Nullable T parent, @Nonnull AssetExtraInfo<K> extraInfo) throws IOException {
|
||||
T t = this.supplier.get();
|
||||
this.dataSetter.accept(t, extraInfo.getData());
|
||||
if (parent != null) {
|
||||
this.inherit(t, parent, extraInfo);
|
||||
}
|
||||
|
||||
this.decodeAndInheritJson0(reader, t, parent, extraInfo);
|
||||
this.idSetter.accept(t, extraInfo.getKey());
|
||||
this.afterDecodeAndValidate(t, extraInfo);
|
||||
return t;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public ObjectSchema toSchema(@Nonnull SchemaContext context) {
|
||||
return this.toSchema(context, this.supplier.get());
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public ObjectSchema toSchema(@Nonnull SchemaContext context, @Nullable T def) {
|
||||
ObjectSchema schema = super.toSchema(context, def);
|
||||
KeyedCodec<K> parent = this.getParentCodec();
|
||||
Schema parentSchema = parent.getChildCodec().toSchema(context);
|
||||
parentSchema.setMarkdownDescription(
|
||||
"When set this asset will inherit properties from the named asset.\n\nWhen inheriting from another **"
|
||||
+ this.tClass.getSimpleName()
|
||||
+ "** most properties will simply be copied from the parent asset to this asset. In the case where both child and parent provide a field the child field will simply replace the value provided by the parent, in the case of nested structures this will apply to the fields within the structure. In some cases the field may decide to act differently, for example: by merging the parent and child fields together."
|
||||
);
|
||||
Class<? super T> rootClass = this.tClass;
|
||||
|
||||
for (BuilderCodec<? super T> rootCodec = this; rootCodec.getParent() != null; rootClass = rootCodec.getInnerClass()) {
|
||||
rootCodec = rootCodec.getParent();
|
||||
}
|
||||
|
||||
parentSchema.setHytaleParent(new Schema.InheritSettings(rootClass.getSimpleName()));
|
||||
LinkedHashMap<String, Schema> props = new LinkedHashMap<>();
|
||||
props.put(parent.getKey(), parentSchema);
|
||||
props.putAll(schema.getProperties());
|
||||
schema.setProperties(props);
|
||||
return schema;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static <K, T extends JsonAsset<K>> AssetBuilderCodec.Builder<K, T> builder(
|
||||
Class<T> tClass,
|
||||
Supplier<T> supplier,
|
||||
Codec<K> idCodec,
|
||||
BiConsumer<T, K> idSetter,
|
||||
Function<T, K> idGetter,
|
||||
BiConsumer<T, AssetExtraInfo.Data> dataSetter,
|
||||
@Nonnull Function<T, AssetExtraInfo.Data> dataGetter
|
||||
) {
|
||||
return new AssetBuilderCodec.Builder<>(tClass, supplier, idCodec, idSetter, idGetter, dataSetter, dataGetter);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static <K, T extends JsonAsset<K>> AssetBuilderCodec.Builder<K, T> builder(
|
||||
Class<T> tClass,
|
||||
Supplier<T> supplier,
|
||||
BuilderCodec<? super T> parentCodec,
|
||||
Codec<K> idCodec,
|
||||
BiConsumer<T, K> idSetter,
|
||||
Function<T, K> idGetter,
|
||||
BiConsumer<T, AssetExtraInfo.Data> dataSetter,
|
||||
@Nonnull Function<T, AssetExtraInfo.Data> dataGetter
|
||||
) {
|
||||
return new AssetBuilderCodec.Builder<>(tClass, supplier, parentCodec, idCodec, idSetter, idGetter, dataSetter, dataGetter);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static <K, T extends JsonAsset<K>> AssetBuilderCodec<K, T> wrap(
|
||||
@Nonnull BuilderCodec<T> codec,
|
||||
Codec<K> idCodec,
|
||||
BiConsumer<T, K> idSetter,
|
||||
Function<T, K> idGetter,
|
||||
BiConsumer<T, AssetExtraInfo.Data> dataSetter,
|
||||
@Nonnull Function<T, AssetExtraInfo.Data> dataGetter
|
||||
) {
|
||||
return builder(codec.getInnerClass(), codec.getSupplier(), codec, idCodec, idSetter, idGetter, dataSetter, dataGetter)
|
||||
.documentation(codec.getDocumentation())
|
||||
.build();
|
||||
}
|
||||
|
||||
public static class Builder<K, T extends JsonAsset<K>> extends BuilderCodec.BuilderBase<T, AssetBuilderCodec.Builder<K, T>> {
|
||||
@Nonnull
|
||||
protected final KeyedCodec<K> idCodec;
|
||||
protected final BiConsumer<T, K> idSetter;
|
||||
protected final BiConsumer<T, AssetExtraInfo.Data> dataSetter;
|
||||
@Nonnull
|
||||
protected final Function<T, AssetExtraInfo.Data> dataGetter;
|
||||
|
||||
public Builder(
|
||||
Class<T> tClass,
|
||||
Supplier<T> supplier,
|
||||
Codec<K> idCodec,
|
||||
BiConsumer<T, K> idSetter,
|
||||
Function<T, K> idGetter,
|
||||
BiConsumer<T, AssetExtraInfo.Data> dataSetter,
|
||||
@Nonnull Function<T, AssetExtraInfo.Data> dataGetter
|
||||
) {
|
||||
super(tClass, supplier);
|
||||
this.idCodec = new KeyedCodec<>("Id", idCodec);
|
||||
this.idSetter = idSetter;
|
||||
this.dataSetter = dataSetter;
|
||||
this.dataGetter = dataGetter;
|
||||
this.<Map<String, String[]>>appendInherited(AssetBuilderCodec.TAGS_CODEC, (t, tags) -> dataGetter.apply(t).putTags(tags), t -> {
|
||||
AssetExtraInfo.Data data = dataGetter.apply(t);
|
||||
return data != null ? data.getRawTags() : null;
|
||||
}, (t, parent) -> {
|
||||
AssetExtraInfo.Data data = dataGetter.apply(t);
|
||||
AssetExtraInfo.Data parentData = dataGetter.apply(parent);
|
||||
if (data != null && parentData != null) {
|
||||
data.putTags(parentData.getRawTags());
|
||||
}
|
||||
})
|
||||
.documentation(
|
||||
"Tags are a general way to describe an asset that can be interpreted by other systems in a way they see fit.\n\nFor example you could tag something with a **Material** tag with the values **Solid** and **Stone**, And another single tag **Ore**.\n\nTags will be expanded into a single list of tags automatically. Using the above example with **Material** and **Ore** the end result would be the following list of tags: **Ore**, **Material**, **Solid**, **Stone**, **Material=Solid** and **Material=Stone**."
|
||||
)
|
||||
.add();
|
||||
}
|
||||
|
||||
public Builder(
|
||||
Class<T> tClass,
|
||||
Supplier<T> supplier,
|
||||
BuilderCodec<? super T> parentCodec,
|
||||
Codec<K> idCodec,
|
||||
BiConsumer<T, K> idSetter,
|
||||
Function<T, K> idGetter,
|
||||
BiConsumer<T, AssetExtraInfo.Data> dataSetter,
|
||||
@Nonnull Function<T, AssetExtraInfo.Data> dataGetter
|
||||
) {
|
||||
super(tClass, supplier, parentCodec);
|
||||
this.idCodec = new KeyedCodec<>("Id", idCodec);
|
||||
this.idSetter = idSetter;
|
||||
this.dataSetter = dataSetter;
|
||||
this.dataGetter = dataGetter;
|
||||
this.<Map<String, String[]>>appendInherited(AssetBuilderCodec.TAGS_CODEC, (t, tags) -> dataGetter.apply(t).putTags(tags), t -> {
|
||||
AssetExtraInfo.Data data = dataGetter.apply(t);
|
||||
return data != null ? data.getRawTags() : null;
|
||||
}, (t, parent) -> {
|
||||
AssetExtraInfo.Data data = dataGetter.apply(t);
|
||||
AssetExtraInfo.Data parentData = dataGetter.apply(parent);
|
||||
if (data != null && parentData != null) {
|
||||
data.putTags(parentData.getRawTags());
|
||||
}
|
||||
})
|
||||
.documentation(
|
||||
"Tags are a general way to describe an asset that can be interpreted by other systems in a way they see fit.\n\nFor example you could tag something with a **Material** tag with the values **Solid** and **Stone**, And another single tag **Ore**.\n\nTags will be expanded into a single list of tags automatically. Using the above example with **Material** and **Ore** the end result would be the following list of tags: **Ore**, **Material**, **Solid**, **Stone**, **Material=Solid** and **Material=Stone**."
|
||||
)
|
||||
.add();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public AssetBuilderCodec<K, T> build() {
|
||||
return new AssetBuilderCodec<>(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
23
src/com/hypixel/hytale/assetstore/codec/AssetCodec.java
Normal file
23
src/com/hypixel/hytale/assetstore/codec/AssetCodec.java
Normal file
@@ -0,0 +1,23 @@
|
||||
package com.hypixel.hytale.assetstore.codec;
|
||||
|
||||
import com.hypixel.hytale.assetstore.AssetExtraInfo;
|
||||
import com.hypixel.hytale.assetstore.JsonAsset;
|
||||
import com.hypixel.hytale.codec.InheritCodec;
|
||||
import com.hypixel.hytale.codec.KeyedCodec;
|
||||
import com.hypixel.hytale.codec.util.RawJsonReader;
|
||||
import com.hypixel.hytale.codec.validation.ValidatableCodec;
|
||||
import java.io.IOException;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public interface AssetCodec<K, T extends JsonAsset<K>> extends InheritCodec<T>, ValidatableCodec<T> {
|
||||
KeyedCodec<K> getKeyCodec();
|
||||
|
||||
KeyedCodec<K> getParentCodec();
|
||||
|
||||
@Nullable
|
||||
AssetExtraInfo.Data getData(T var1);
|
||||
|
||||
T decodeJsonAsset(RawJsonReader var1, AssetExtraInfo<K> var2) throws IOException;
|
||||
|
||||
T decodeAndInheritJsonAsset(RawJsonReader var1, T var2, AssetExtraInfo<K> var3) throws IOException;
|
||||
}
|
||||
308
src/com/hypixel/hytale/assetstore/codec/AssetCodecMapCodec.java
Normal file
308
src/com/hypixel/hytale/assetstore/codec/AssetCodecMapCodec.java
Normal file
@@ -0,0 +1,308 @@
|
||||
package com.hypixel.hytale.assetstore.codec;
|
||||
|
||||
import com.hypixel.hytale.assetstore.AssetExtraInfo;
|
||||
import com.hypixel.hytale.assetstore.JsonAsset;
|
||||
import com.hypixel.hytale.codec.Codec;
|
||||
import com.hypixel.hytale.codec.ExtraInfo;
|
||||
import com.hypixel.hytale.codec.KeyedCodec;
|
||||
import com.hypixel.hytale.codec.builder.BuilderCodec;
|
||||
import com.hypixel.hytale.codec.exception.CodecException;
|
||||
import com.hypixel.hytale.codec.lookup.ACodecMapCodec;
|
||||
import com.hypixel.hytale.codec.lookup.Priority;
|
||||
import com.hypixel.hytale.codec.lookup.StringCodecMapCodec;
|
||||
import com.hypixel.hytale.codec.schema.SchemaContext;
|
||||
import com.hypixel.hytale.codec.schema.config.ObjectSchema;
|
||||
import com.hypixel.hytale.codec.schema.config.Schema;
|
||||
import com.hypixel.hytale.codec.util.RawJsonReader;
|
||||
import java.io.IOException;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import org.bson.BsonDocument;
|
||||
import org.bson.BsonValue;
|
||||
|
||||
public class AssetCodecMapCodec<K, T extends JsonAsset<K>> extends StringCodecMapCodec<T, AssetBuilderCodec<K, T>> implements AssetCodec<K, T> {
|
||||
@Nonnull
|
||||
protected final KeyedCodec<K> idCodec;
|
||||
@Nonnull
|
||||
protected final KeyedCodec<K> parentCodec;
|
||||
protected final BiConsumer<T, K> idSetter;
|
||||
protected final Function<T, K> idGetter;
|
||||
protected final BiConsumer<T, AssetExtraInfo.Data> dataSetter;
|
||||
protected final Function<T, AssetExtraInfo.Data> dataGetter;
|
||||
|
||||
public AssetCodecMapCodec(
|
||||
Codec<K> idCodec,
|
||||
BiConsumer<T, K> idSetter,
|
||||
Function<T, K> idGetter,
|
||||
BiConsumer<T, AssetExtraInfo.Data> dataSetter,
|
||||
Function<T, AssetExtraInfo.Data> dataGetter
|
||||
) {
|
||||
super("Type");
|
||||
this.idCodec = new KeyedCodec<>("Id", idCodec);
|
||||
this.parentCodec = new KeyedCodec<>("Parent", idCodec);
|
||||
this.idSetter = idSetter;
|
||||
this.idGetter = idGetter;
|
||||
this.dataSetter = dataSetter;
|
||||
this.dataGetter = dataGetter;
|
||||
}
|
||||
|
||||
public AssetCodecMapCodec(
|
||||
String key,
|
||||
Codec<K> idCodec,
|
||||
BiConsumer<T, K> idSetter,
|
||||
Function<T, K> idGetter,
|
||||
BiConsumer<T, AssetExtraInfo.Data> dataSetter,
|
||||
Function<T, AssetExtraInfo.Data> dataGetter
|
||||
) {
|
||||
super(key);
|
||||
this.idCodec = new KeyedCodec<>("Id", idCodec);
|
||||
this.parentCodec = new KeyedCodec<>("Parent", idCodec);
|
||||
this.idSetter = idSetter;
|
||||
this.idGetter = idGetter;
|
||||
this.dataSetter = dataSetter;
|
||||
this.dataGetter = dataGetter;
|
||||
}
|
||||
|
||||
public AssetCodecMapCodec(
|
||||
Codec<K> idCodec,
|
||||
BiConsumer<T, K> idSetter,
|
||||
Function<T, K> idGetter,
|
||||
BiConsumer<T, AssetExtraInfo.Data> dataSetter,
|
||||
Function<T, AssetExtraInfo.Data> dataGetter,
|
||||
boolean allowDefault
|
||||
) {
|
||||
super("Type", allowDefault);
|
||||
this.idCodec = new KeyedCodec<>("Id", idCodec);
|
||||
this.parentCodec = new KeyedCodec<>("Parent", idCodec);
|
||||
this.idSetter = idSetter;
|
||||
this.idGetter = idGetter;
|
||||
this.dataSetter = dataSetter;
|
||||
this.dataGetter = dataGetter;
|
||||
}
|
||||
|
||||
public AssetCodecMapCodec(
|
||||
String key,
|
||||
Codec<K> idCodec,
|
||||
BiConsumer<T, K> idSetter,
|
||||
Function<T, K> idGetter,
|
||||
BiConsumer<T, AssetExtraInfo.Data> dataSetter,
|
||||
Function<T, AssetExtraInfo.Data> dataGetter,
|
||||
boolean allowDefault
|
||||
) {
|
||||
super(key, allowDefault);
|
||||
this.idCodec = new KeyedCodec<>("Id", idCodec);
|
||||
this.parentCodec = new KeyedCodec<>("Parent", idCodec);
|
||||
this.idSetter = idSetter;
|
||||
this.idGetter = idGetter;
|
||||
this.dataSetter = dataSetter;
|
||||
this.dataGetter = dataGetter;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public KeyedCodec<K> getKeyCodec() {
|
||||
return this.idCodec;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public KeyedCodec<K> getParentCodec() {
|
||||
return this.parentCodec;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AssetExtraInfo.Data getData(T t) {
|
||||
return this.dataGetter.apply(t);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public AssetCodecMapCodec<K, T> register(@Nonnull String id, Class<? extends T> aClass, BuilderCodec<? extends T> codec) {
|
||||
return this.register(Priority.NORMAL, id, aClass, codec);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public AssetCodecMapCodec<K, T> register(@Nonnull Priority priority, @Nonnull String id, Class<? extends T> aClass, BuilderCodec<? extends T> codec) {
|
||||
AssetBuilderCodec<K, T> assetCodec = AssetBuilderCodec.wrap(
|
||||
(BuilderCodec<T>)codec, this.idCodec.getChildCodec(), this.idSetter, this.idGetter, this.dataSetter, this.dataGetter
|
||||
);
|
||||
super.register(priority, id, aClass, assetCodec);
|
||||
return this;
|
||||
}
|
||||
|
||||
public T decodeAndInherit(@Nonnull BsonDocument document, T parent, ExtraInfo extraInfo) {
|
||||
BsonValue id = document.get(this.key);
|
||||
AssetBuilderCodec<K, T> codec = this.idToCodec.get(id == null ? null : id.asString().getValue());
|
||||
if (codec == null) {
|
||||
AssetBuilderCodec<K, T> defaultCodec = this.getDefaultCodec();
|
||||
if (defaultCodec == null) {
|
||||
throw new ACodecMapCodec.UnknownIdException("No codec registered with for '" + this.key + "': " + id);
|
||||
} else {
|
||||
return defaultCodec.decodeAndInherit(document, parent, extraInfo);
|
||||
}
|
||||
} else {
|
||||
return codec.decodeAndInherit(document, parent, extraInfo);
|
||||
}
|
||||
}
|
||||
|
||||
public void decodeAndInherit(@Nonnull BsonDocument document, T t, T parent, ExtraInfo extraInfo) {
|
||||
BsonValue id = document.get(this.key);
|
||||
AssetBuilderCodec<K, T> codec = this.idToCodec.get(id == null ? null : id.asString().getValue());
|
||||
if (codec == null) {
|
||||
AssetBuilderCodec<K, T> defaultCodec = this.getDefaultCodec();
|
||||
if (defaultCodec == null) {
|
||||
throw new ACodecMapCodec.UnknownIdException("No codec registered with for '" + this.key + "': " + id);
|
||||
} else {
|
||||
defaultCodec.decodeAndInherit(document, t, parent, extraInfo);
|
||||
}
|
||||
} else {
|
||||
codec.decodeAndInherit(document, t, parent, extraInfo);
|
||||
}
|
||||
}
|
||||
|
||||
public T decodeAndInheritJson(@Nonnull RawJsonReader reader, @Nullable T parent, @Nonnull ExtraInfo extraInfo) throws IOException {
|
||||
reader.mark();
|
||||
String id = null;
|
||||
if (RawJsonReader.seekToKey(reader, this.key)) {
|
||||
id = reader.readString();
|
||||
} else if (parent != null) {
|
||||
id = this.getIdFor((Class<? extends T>)parent.getClass());
|
||||
}
|
||||
|
||||
reader.reset();
|
||||
extraInfo.ignoreUnusedKey(this.key);
|
||||
|
||||
JsonAsset var7;
|
||||
try {
|
||||
AssetBuilderCodec<K, T> codec = id == null ? null : this.idToCodec.get(id);
|
||||
if (codec != null) {
|
||||
return codec.decodeAndInheritJson(reader, parent, extraInfo);
|
||||
}
|
||||
|
||||
AssetBuilderCodec<K, T> defaultCodec = this.getDefaultCodec();
|
||||
if (defaultCodec == null) {
|
||||
throw new ACodecMapCodec.UnknownIdException("No codec registered with for '" + this.key + "': " + id);
|
||||
}
|
||||
|
||||
var7 = defaultCodec.decodeAndInheritJson(reader, parent, extraInfo);
|
||||
} finally {
|
||||
extraInfo.popIgnoredUnusedKey();
|
||||
}
|
||||
|
||||
return (T)var7;
|
||||
}
|
||||
|
||||
public void decodeAndInheritJson(@Nonnull RawJsonReader reader, T t, @Nullable T parent, @Nonnull ExtraInfo extraInfo) throws IOException {
|
||||
reader.mark();
|
||||
String id = null;
|
||||
if (RawJsonReader.seekToKey(reader, this.key)) {
|
||||
id = reader.readString();
|
||||
} else if (parent != null) {
|
||||
id = this.getIdFor((Class<? extends T>)parent.getClass());
|
||||
}
|
||||
|
||||
reader.reset();
|
||||
extraInfo.ignoreUnusedKey(this.key);
|
||||
|
||||
try {
|
||||
AssetBuilderCodec<K, T> codec = id == null ? null : this.idToCodec.get(id);
|
||||
if (codec != null) {
|
||||
codec.decodeAndInheritJson(reader, t, parent, extraInfo);
|
||||
return;
|
||||
}
|
||||
|
||||
AssetBuilderCodec<K, T> defaultCodec = this.getDefaultCodec();
|
||||
if (defaultCodec == null) {
|
||||
throw new ACodecMapCodec.UnknownIdException("No codec registered with for '" + this.key + "': " + id);
|
||||
}
|
||||
|
||||
defaultCodec.decodeAndInheritJson(reader, t, parent, extraInfo);
|
||||
} finally {
|
||||
extraInfo.popIgnoredUnusedKey();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public T decodeJsonAsset(@Nonnull RawJsonReader reader, @Nonnull AssetExtraInfo<K> extraInfo) throws IOException {
|
||||
return this.decodeAndInheritJsonAsset(reader, null, extraInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T decodeAndInheritJsonAsset(@Nonnull RawJsonReader reader, @Nullable T parent, @Nonnull AssetExtraInfo<K> extraInfo) throws IOException {
|
||||
reader.mark();
|
||||
String id = null;
|
||||
if (RawJsonReader.seekToKey(reader, this.key)) {
|
||||
id = reader.readString();
|
||||
} else if (parent != null) {
|
||||
id = this.getIdFor((Class<? extends T>)parent.getClass());
|
||||
}
|
||||
|
||||
reader.reset();
|
||||
extraInfo.ignoreUnusedKey(this.key);
|
||||
|
||||
JsonAsset var8;
|
||||
try {
|
||||
AssetBuilderCodec<K, T> codec = id == null ? null : this.idToCodec.get(id);
|
||||
if (codec == null) {
|
||||
AssetBuilderCodec<K, T> defaultCodec = this.getDefaultCodec();
|
||||
if (defaultCodec == null) {
|
||||
throw new ACodecMapCodec.UnknownIdException("No codec registered with for '" + this.key + "': " + id);
|
||||
}
|
||||
|
||||
codec = defaultCodec;
|
||||
}
|
||||
|
||||
Supplier<T> supplier = codec.getSupplier();
|
||||
if (supplier == null) {
|
||||
throw new CodecException(
|
||||
"This BuilderCodec is for an abstract or direct codec. To use this codec you must specify an existing object to decode into."
|
||||
);
|
||||
}
|
||||
|
||||
T t = supplier.get();
|
||||
this.dataSetter.accept(t, extraInfo.getData());
|
||||
if (parent != null) {
|
||||
codec.inherit(t, parent, extraInfo);
|
||||
}
|
||||
|
||||
codec.decodeAndInheritJson0(reader, t, parent, extraInfo);
|
||||
this.idSetter.accept(t, extraInfo.getKey());
|
||||
codec.afterDecodeAndValidate(t, extraInfo);
|
||||
var8 = t;
|
||||
} finally {
|
||||
extraInfo.popIgnoredUnusedKey();
|
||||
}
|
||||
|
||||
return (T)var8;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public Schema toSchema(@Nonnull SchemaContext context) {
|
||||
Schema schema = super.toSchema(context);
|
||||
schema.getHytaleSchemaTypeField().setParentPropertyKey(this.parentCodec.getKey());
|
||||
return schema;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void mutateChildSchema(String key, @Nonnull SchemaContext context, BuilderCodec<? extends T> c, @Nonnull ObjectSchema objectSchema) {
|
||||
super.mutateChildSchema(key, context, c, objectSchema);
|
||||
AssetBuilderCodec<K, T> def = this.getDefaultCodec();
|
||||
if (!this.allowDefault || def != c) {
|
||||
Schema idField = new Schema();
|
||||
idField.setRequired(this.key);
|
||||
Schema parentField = new Schema();
|
||||
parentField.setRequired(this.parentCodec.getKey());
|
||||
AssetBuilderCodec<K, T> bc = (AssetBuilderCodec<K, T>)c;
|
||||
Schema parentSchema = objectSchema.getProperties().get(bc.getParentCodec().getKey());
|
||||
if (parentSchema != null) {
|
||||
Schema.InheritSettings settings = parentSchema.getHytaleParent();
|
||||
settings.setMapKey(this.key);
|
||||
settings.setMapKeyValue(key);
|
||||
objectSchema.setOneOf(idField, parentField);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
234
src/com/hypixel/hytale/assetstore/codec/ContainedAssetCodec.java
Normal file
234
src/com/hypixel/hytale/assetstore/codec/ContainedAssetCodec.java
Normal file
@@ -0,0 +1,234 @@
|
||||
package com.hypixel.hytale.assetstore.codec;
|
||||
|
||||
import com.hypixel.hytale.assetstore.AssetExtraInfo;
|
||||
import com.hypixel.hytale.assetstore.AssetMap;
|
||||
import com.hypixel.hytale.assetstore.AssetRegistry;
|
||||
import com.hypixel.hytale.assetstore.AssetStore;
|
||||
import com.hypixel.hytale.assetstore.RawAsset;
|
||||
import com.hypixel.hytale.assetstore.map.JsonAssetWithMap;
|
||||
import com.hypixel.hytale.codec.Codec;
|
||||
import com.hypixel.hytale.codec.ExtraInfo;
|
||||
import com.hypixel.hytale.codec.KeyedCodec;
|
||||
import com.hypixel.hytale.codec.schema.SchemaContext;
|
||||
import com.hypixel.hytale.codec.schema.config.Schema;
|
||||
import com.hypixel.hytale.codec.util.RawJsonReader;
|
||||
import com.hypixel.hytale.codec.validation.ValidatableCodec;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import org.bson.BsonValue;
|
||||
|
||||
public class ContainedAssetCodec<K, T extends JsonAssetWithMap<K, M>, M extends AssetMap<K, T>> implements Codec<K>, ValidatableCodec<K> {
|
||||
private static final boolean DISABLE_DIRECT_LOADING = true;
|
||||
private final Class<T> assetClass;
|
||||
private final AssetCodec<K, T> codec;
|
||||
@Nonnull
|
||||
private final ContainedAssetCodec.Mode mode;
|
||||
private final Function<AssetExtraInfo<K>, K> keyGenerator;
|
||||
|
||||
public ContainedAssetCodec(Class<T> assetClass, AssetCodec<K, T> codec) {
|
||||
this(assetClass, codec, ContainedAssetCodec.Mode.GENERATE_ID);
|
||||
}
|
||||
|
||||
public ContainedAssetCodec(Class<T> assetClass, AssetCodec<K, T> codec, @Nonnull ContainedAssetCodec.Mode mode) {
|
||||
this(assetClass, codec, mode, assetExtraInfo -> AssetRegistry.<K, T, M>getAssetStore(assetClass).transformKey(assetExtraInfo.generateKey()));
|
||||
}
|
||||
|
||||
public ContainedAssetCodec(Class<T> assetClass, AssetCodec<K, T> codec, @Nonnull ContainedAssetCodec.Mode mode, Function<AssetExtraInfo<K>, K> keyGenerator) {
|
||||
if (mode == ContainedAssetCodec.Mode.NONE) {
|
||||
throw new UnsupportedOperationException("Contained asset mode can't be NONE!");
|
||||
} else {
|
||||
this.assetClass = assetClass;
|
||||
this.codec = codec;
|
||||
this.mode = mode;
|
||||
this.keyGenerator = keyGenerator;
|
||||
}
|
||||
}
|
||||
|
||||
public Class<T> getAssetClass() {
|
||||
return this.assetClass;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public K decode(@Nonnull BsonValue bsonValue, ExtraInfo extraInfo) {
|
||||
if (!(extraInfo instanceof AssetExtraInfo<K> assetExtraInfo)) {
|
||||
throw new UnsupportedOperationException("Unable to decode asset from codec used outside of an AssetStore");
|
||||
} else if (bsonValue.isString()) {
|
||||
return this.codec.getKeyCodec().getChildCodec().decode(bsonValue, extraInfo);
|
||||
} else {
|
||||
KeyedCodec<K> parentCodec = this.codec.getParentCodec();
|
||||
K parentId = parentCodec != null ? parentCodec.getOrNull(bsonValue.asDocument(), extraInfo) : null;
|
||||
AssetStore<K, T, M> assetStore = AssetRegistry.getAssetStore(this.assetClass);
|
||||
K id;
|
||||
switch (this.mode) {
|
||||
case GENERATE_ID: {
|
||||
id = this.keyGenerator.apply(assetExtraInfo);
|
||||
boolean inheritContainerTags = false;
|
||||
break;
|
||||
}
|
||||
case INHERIT_ID: {
|
||||
id = assetStore.transformKey(assetExtraInfo.getKey());
|
||||
boolean inheritContainerTags = true;
|
||||
break;
|
||||
}
|
||||
case INHERIT_ID_AND_PARENT: {
|
||||
id = assetStore.transformKey(assetExtraInfo.getKey());
|
||||
if (parentId == null) {
|
||||
Object thisAssetParentId = assetExtraInfo.getData().getParentKey();
|
||||
if (thisAssetParentId != null) {
|
||||
parentId = assetStore.transformKey(thisAssetParentId);
|
||||
}
|
||||
}
|
||||
|
||||
boolean inheritContainerTags = true;
|
||||
break;
|
||||
}
|
||||
case INJECT_PARENT: {
|
||||
id = this.keyGenerator.apply(assetExtraInfo);
|
||||
if (parentId == null && !assetExtraInfo.getKey().equals(id)) {
|
||||
parentId = assetExtraInfo.getKey();
|
||||
}
|
||||
|
||||
boolean inheritContainerTags = true;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new UnsupportedOperationException("Contained asset mode can't be NONE!");
|
||||
}
|
||||
|
||||
T parent = parentId != null ? assetStore.getAssetMap().getAsset(parentId) : null;
|
||||
if (parentId != null && parent != null) {
|
||||
}
|
||||
|
||||
char[] clone = bsonValue.asDocument().toJson().toCharArray();
|
||||
Path path = assetExtraInfo.getAssetPath();
|
||||
assetExtraInfo.getData().addContainedAsset(this.assetClass, new RawAsset<>(path, id, parentId, 0, clone, assetExtraInfo.getData(), this.mode));
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public BsonValue encode(@Nonnull K key, ExtraInfo extraInfo) {
|
||||
if (key.toString().startsWith("*")) {
|
||||
T asset = (T)AssetRegistry.<K, T, M>getAssetStore(this.assetClass).getAssetMap().getAsset(key);
|
||||
if (asset != null) {
|
||||
return this.codec.encode(asset, extraInfo);
|
||||
}
|
||||
}
|
||||
|
||||
return this.codec.getKeyCodec().getChildCodec().encode(key, extraInfo);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public K decodeJson(@Nonnull RawJsonReader reader, ExtraInfo extraInfo) throws IOException {
|
||||
if (!(extraInfo instanceof AssetExtraInfo<K> assetExtraInfo)) {
|
||||
throw new UnsupportedOperationException("Unable to decode asset from codec used outside of an AssetStore");
|
||||
} else {
|
||||
int lineStart = reader.getLine() - 1;
|
||||
if (reader.peekFor('"')) {
|
||||
return this.codec.getKeyCodec().getChildCodec().decodeJson(reader, extraInfo);
|
||||
} else {
|
||||
reader.mark();
|
||||
K parentId = null;
|
||||
boolean needsSkip = false;
|
||||
KeyedCodec<K> parentCodec = this.codec.getParentCodec();
|
||||
if (parentCodec != null && RawJsonReader.seekToKey(reader, parentCodec.getKey())) {
|
||||
parentId = parentCodec.getChildCodec().decodeJson(reader, extraInfo);
|
||||
needsSkip = true;
|
||||
}
|
||||
|
||||
AssetStore<K, T, M> assetStore = AssetRegistry.getAssetStore(this.assetClass);
|
||||
K id;
|
||||
switch (this.mode) {
|
||||
case GENERATE_ID: {
|
||||
id = this.keyGenerator.apply(assetExtraInfo);
|
||||
boolean inheritContainerTags = false;
|
||||
break;
|
||||
}
|
||||
case INHERIT_ID: {
|
||||
id = assetStore.transformKey(assetExtraInfo.getKey());
|
||||
boolean inheritContainerTags = true;
|
||||
break;
|
||||
}
|
||||
case INHERIT_ID_AND_PARENT: {
|
||||
id = assetStore.transformKey(assetExtraInfo.getKey());
|
||||
if (parentId == null) {
|
||||
Object thisAssetParentId = assetExtraInfo.getData().getParentKey();
|
||||
if (thisAssetParentId != null) {
|
||||
parentId = assetStore.transformKey(thisAssetParentId);
|
||||
}
|
||||
}
|
||||
|
||||
boolean inheritContainerTags = true;
|
||||
break;
|
||||
}
|
||||
case INJECT_PARENT: {
|
||||
id = this.keyGenerator.apply(assetExtraInfo);
|
||||
if (parentId == null && !assetExtraInfo.getKey().equals(id)) {
|
||||
parentId = assetExtraInfo.getKey();
|
||||
}
|
||||
|
||||
boolean inheritContainerTags = true;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new UnsupportedOperationException("Contained asset mode can't be NONE!");
|
||||
}
|
||||
|
||||
T parent = parentId != null ? assetStore.getAssetMap().getAsset(parentId) : null;
|
||||
if (parentId != null && parent != null) {
|
||||
}
|
||||
|
||||
if (needsSkip) {
|
||||
reader.skipObjectContinued();
|
||||
}
|
||||
|
||||
char[] clone = reader.cloneMark();
|
||||
reader.unmark();
|
||||
Path path = assetExtraInfo.getAssetPath();
|
||||
assetExtraInfo.getData()
|
||||
.addContainedAsset(this.assetClass, new RawAsset<>(path, id, parentId, lineStart, clone, assetExtraInfo.getData(), this.mode));
|
||||
return id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public Schema toSchema(@Nonnull SchemaContext context) {
|
||||
Schema keySchema = context.refDefinition(this.codec.getKeyCodec().getChildCodec());
|
||||
keySchema.setTitle("Reference to " + this.assetClass.getSimpleName());
|
||||
Schema nestedSchema = context.refDefinition(this.codec);
|
||||
Schema s = Schema.anyOf(keySchema, nestedSchema);
|
||||
s.setHytaleAssetRef(this.assetClass.getSimpleName());
|
||||
return s;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validate(K k, @Nonnull ExtraInfo extraInfo) {
|
||||
AssetRegistry.<K, T, M>getAssetStore(this.assetClass).validate(k, extraInfo.getValidationResults(), extraInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validateDefaults(ExtraInfo extraInfo, @Nonnull Set<Codec<?>> tested) {
|
||||
if (tested.add(this)) {
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
public static enum Mode {
|
||||
NONE,
|
||||
GENERATE_ID,
|
||||
INHERIT_ID,
|
||||
INHERIT_ID_AND_PARENT,
|
||||
INJECT_PARENT;
|
||||
|
||||
private Mode() {
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package com.hypixel.hytale.assetstore.event;
|
||||
|
||||
import com.hypixel.hytale.event.IEvent;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public abstract class AssetMonitorEvent<T> implements IEvent<T> {
|
||||
@Nonnull
|
||||
private final List<Path> createdOrModifiedFilesToLoad;
|
||||
@Nonnull
|
||||
private final List<Path> removedFilesToUnload;
|
||||
@Nonnull
|
||||
private final List<Path> createdOrModifiedDirectories;
|
||||
@Nonnull
|
||||
private final List<Path> removedFilesAndDirectories;
|
||||
@Nonnull
|
||||
private final String assetPack;
|
||||
|
||||
public AssetMonitorEvent(
|
||||
@Nonnull String assetPack,
|
||||
@Nonnull List<Path> createdOrModified,
|
||||
@Nonnull List<Path> removed,
|
||||
@Nonnull List<Path> createdDirectories,
|
||||
@Nonnull List<Path> removedDirectories
|
||||
) {
|
||||
this.assetPack = assetPack;
|
||||
this.createdOrModifiedFilesToLoad = createdOrModified;
|
||||
this.removedFilesToUnload = removed;
|
||||
this.createdOrModifiedDirectories = createdDirectories;
|
||||
this.removedFilesAndDirectories = removedDirectories;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public String getAssetPack() {
|
||||
return this.assetPack;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public List<Path> getCreatedOrModifiedFilesToLoad() {
|
||||
return this.createdOrModifiedFilesToLoad;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public List<Path> getRemovedFilesToUnload() {
|
||||
return this.removedFilesToUnload;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public List<Path> getRemovedFilesAndDirectories() {
|
||||
return this.removedFilesAndDirectories;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public List<Path> getCreatedOrModifiedDirectories() {
|
||||
return this.createdOrModifiedDirectories;
|
||||
}
|
||||
}
|
||||
25
src/com/hypixel/hytale/assetstore/event/AssetStoreEvent.java
Normal file
25
src/com/hypixel/hytale/assetstore/event/AssetStoreEvent.java
Normal file
@@ -0,0 +1,25 @@
|
||||
package com.hypixel.hytale.assetstore.event;
|
||||
|
||||
import com.hypixel.hytale.assetstore.AssetStore;
|
||||
import com.hypixel.hytale.event.IEvent;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public abstract class AssetStoreEvent<KeyType> implements IEvent<KeyType> {
|
||||
@Nonnull
|
||||
private final AssetStore<?, ?, ?> assetStore;
|
||||
|
||||
public AssetStoreEvent(@Nonnull AssetStore<?, ?, ?> assetStore) {
|
||||
this.assetStore = assetStore;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public AssetStore<?, ?, ?> getAssetStore() {
|
||||
return this.assetStore;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public String toString() {
|
||||
return "AssetStoreEvent{assetStore=" + this.assetStore + "}";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.hypixel.hytale.assetstore.event;
|
||||
|
||||
import com.hypixel.hytale.assetstore.AssetStore;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class AssetStoreMonitorEvent extends AssetMonitorEvent<Void> {
|
||||
@Nonnull
|
||||
private final AssetStore<?, ?, ?> assetStore;
|
||||
|
||||
public AssetStoreMonitorEvent(
|
||||
@Nonnull String assetPack,
|
||||
@Nonnull AssetStore<?, ?, ?> assetStore,
|
||||
@Nonnull List<Path> createdOrModified,
|
||||
@Nonnull List<Path> removed,
|
||||
@Nonnull List<Path> createdOrModifiedDirectories,
|
||||
@Nonnull List<Path> removedDirectories
|
||||
) {
|
||||
super(assetPack, createdOrModified, removed, createdOrModifiedDirectories, removedDirectories);
|
||||
this.assetStore = assetStore;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public AssetStore<?, ?, ?> getAssetStore() {
|
||||
return this.assetStore;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public String toString() {
|
||||
return "AssetMonitorEvent{assetStore=" + this.assetStore + "}";
|
||||
}
|
||||
}
|
||||
9
src/com/hypixel/hytale/assetstore/event/AssetsEvent.java
Normal file
9
src/com/hypixel/hytale/assetstore/event/AssetsEvent.java
Normal file
@@ -0,0 +1,9 @@
|
||||
package com.hypixel.hytale.assetstore.event;
|
||||
|
||||
import com.hypixel.hytale.assetstore.JsonAsset;
|
||||
import com.hypixel.hytale.event.IEvent;
|
||||
|
||||
public abstract class AssetsEvent<K, T extends JsonAsset<K>> implements IEvent<Class<T>> {
|
||||
public AssetsEvent() {
|
||||
}
|
||||
}
|
||||
201
src/com/hypixel/hytale/assetstore/event/GenerateAssetsEvent.java
Normal file
201
src/com/hypixel/hytale/assetstore/event/GenerateAssetsEvent.java
Normal file
@@ -0,0 +1,201 @@
|
||||
package com.hypixel.hytale.assetstore.event;
|
||||
|
||||
import com.hypixel.hytale.assetstore.AssetExtraInfo;
|
||||
import com.hypixel.hytale.assetstore.AssetMap;
|
||||
import com.hypixel.hytale.assetstore.AssetRegistry;
|
||||
import com.hypixel.hytale.assetstore.AssetStore;
|
||||
import com.hypixel.hytale.assetstore.map.JsonAssetWithMap;
|
||||
import com.hypixel.hytale.common.util.FormatUtil;
|
||||
import com.hypixel.hytale.event.IProcessedEvent;
|
||||
import com.hypixel.hytale.logger.HytaleLogger;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.logging.Level;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class GenerateAssetsEvent<K, T extends JsonAssetWithMap<K, M>, M extends AssetMap<K, T>> extends AssetsEvent<K, T> implements IProcessedEvent {
|
||||
private final Class<T> tClass;
|
||||
private final M assetMap;
|
||||
@Nonnull
|
||||
private final Map<K, T> loadedAssets;
|
||||
private final Map<K, Set<K>> assetChildren;
|
||||
@Nonnull
|
||||
private final Map<K, T> unmodifiableLoadedAssets;
|
||||
private final Map<K, T> addedAssets = new ConcurrentHashMap<>();
|
||||
private final Map<K, Set<K>> addedAssetChildren = new ConcurrentHashMap<>();
|
||||
private final Map<Class<? extends JsonAssetWithMap<?, ?>>, Map<?, Set<K>>> addedChildAssetsMap = new ConcurrentHashMap<>();
|
||||
private long before;
|
||||
|
||||
public GenerateAssetsEvent(Class<T> tClass, M assetMap, @Nonnull Map<K, T> loadedAssets, Map<K, Set<K>> assetChildren) {
|
||||
this.tClass = tClass;
|
||||
this.assetMap = assetMap;
|
||||
this.loadedAssets = loadedAssets;
|
||||
this.assetChildren = assetChildren;
|
||||
this.unmodifiableLoadedAssets = Collections.unmodifiableMap(loadedAssets);
|
||||
this.before = System.nanoTime();
|
||||
}
|
||||
|
||||
public Class<T> getAssetClass() {
|
||||
return this.tClass;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public Map<K, T> getLoadedAssets() {
|
||||
return this.unmodifiableLoadedAssets;
|
||||
}
|
||||
|
||||
public M getAssetMap() {
|
||||
return this.assetMap;
|
||||
}
|
||||
|
||||
public void addChildAsset(K childKey, T asset, @Nonnull K parent) {
|
||||
if (!this.loadedAssets.containsKey(parent) && this.assetMap.getAsset(parent) == null) {
|
||||
throw new IllegalArgumentException("Parent '" + parent + "' doesn't exist!");
|
||||
} else if (parent.equals(childKey)) {
|
||||
throw new IllegalArgumentException("Unable to to add asset '" + parent + "' because it is its own parent!");
|
||||
} else {
|
||||
AssetStore<K, T, M> assetStore = AssetRegistry.getAssetStore(this.tClass);
|
||||
AssetExtraInfo<K> extraInfo = new AssetExtraInfo<>(assetStore.getCodec().getData(asset));
|
||||
assetStore.getCodec().validate(asset, extraInfo);
|
||||
extraInfo.getValidationResults().logOrThrowValidatorExceptions(assetStore.getLogger());
|
||||
this.addedAssets.put(childKey, asset);
|
||||
this.addedAssetChildren.computeIfAbsent(parent, k -> new HashSet<>()).add(childKey);
|
||||
}
|
||||
}
|
||||
|
||||
@SafeVarargs
|
||||
public final void addChildAsset(K childKey, T asset, @Nonnull K... parents) {
|
||||
for (int i = 0; i < parents.length; i++) {
|
||||
K parent = parents[i];
|
||||
if (!this.loadedAssets.containsKey(parent) && this.assetMap.getAsset(parent) == null) {
|
||||
throw new IllegalArgumentException("Parent at " + i + " '" + parent + "' doesn't exist!");
|
||||
}
|
||||
|
||||
if (parent.equals(childKey)) {
|
||||
throw new IllegalArgumentException("Unable to to add asset '" + parent + "' because it is its own parent!");
|
||||
}
|
||||
}
|
||||
|
||||
AssetStore<K, T, M> assetStore = AssetRegistry.getAssetStore(this.tClass);
|
||||
AssetExtraInfo<K> extraInfo = new AssetExtraInfo<>(assetStore.getCodec().getData(asset));
|
||||
assetStore.getCodec().validate(asset, extraInfo);
|
||||
extraInfo.getValidationResults().logOrThrowValidatorExceptions(assetStore.getLogger());
|
||||
this.addedAssets.put(childKey, asset);
|
||||
|
||||
for (K parentx : parents) {
|
||||
this.addedAssetChildren.computeIfAbsent(parentx, k -> new HashSet<>()).add(childKey);
|
||||
}
|
||||
}
|
||||
|
||||
public <P extends JsonAssetWithMap<PK, ?>, PK> void addChildAssetWithReference(K childKey, T asset, Class<P> parentAssetClass, @Nonnull PK parentKey) {
|
||||
if (AssetRegistry.<PK, T, AssetMap<PK, T>>getAssetStore(parentAssetClass).getAssetMap().getAsset(parentKey) == null) {
|
||||
throw new IllegalArgumentException("Parent '" + parentKey + "' from " + parentAssetClass + " doesn't exist!");
|
||||
} else if (parentKey.equals(childKey)) {
|
||||
throw new IllegalArgumentException("Unable to to add asset '" + parentKey + "' because it is its own parent!");
|
||||
} else {
|
||||
AssetStore<K, T, M> assetStore = AssetRegistry.getAssetStore(this.tClass);
|
||||
AssetExtraInfo<K> extraInfo = new AssetExtraInfo<>(assetStore.getCodec().getData(asset));
|
||||
assetStore.getCodec().validate(asset, extraInfo);
|
||||
extraInfo.getValidationResults().logOrThrowValidatorExceptions(assetStore.getLogger());
|
||||
this.addedAssets.put(childKey, asset);
|
||||
((Map<PK, Set<K>>)this.addedChildAssetsMap
|
||||
.computeIfAbsent(parentAssetClass, k -> new ConcurrentHashMap<>()))
|
||||
.computeIfAbsent(parentKey, k -> new HashSet())
|
||||
.add(childKey);
|
||||
}
|
||||
}
|
||||
|
||||
public void addChildAssetWithReferences(K childKey, T asset, @Nonnull GenerateAssetsEvent.ParentReference<?, ?>... parents) {
|
||||
for (int i = 0; i < parents.length; i++) {
|
||||
GenerateAssetsEvent.ParentReference<?, ?> parent = parents[i];
|
||||
if (AssetRegistry.getAssetStore(parent.getParentAssetClass()).getAssetMap().getAsset((K)parent.getParentKey()) == null) {
|
||||
throw new IllegalArgumentException("Parent at " + i + " '" + parent + "' doesn't exist!");
|
||||
}
|
||||
|
||||
if (parent.parentKey.equals(childKey)) {
|
||||
throw new IllegalArgumentException("Unable to to add asset '" + parent.parentKey + "' because it is its own parent!");
|
||||
}
|
||||
}
|
||||
|
||||
AssetStore<K, T, M> assetStore = AssetRegistry.getAssetStore(this.tClass);
|
||||
AssetExtraInfo<K> extraInfo = new AssetExtraInfo<>(assetStore.getCodec().getData(asset));
|
||||
assetStore.getCodec().validate(asset, extraInfo);
|
||||
extraInfo.getValidationResults().logOrThrowValidatorExceptions(assetStore.getLogger());
|
||||
this.addedAssets.put(childKey, asset);
|
||||
|
||||
for (GenerateAssetsEvent.ParentReference<?, ?> parentx : parents) {
|
||||
((Map<Object, Set<K>>)this.addedChildAssetsMap
|
||||
.computeIfAbsent((Class<? extends JsonAssetWithMap<?, ?>>)parentx.parentAssetClass, k -> new ConcurrentHashMap<>()))
|
||||
.computeIfAbsent(parentx.parentKey, k -> new HashSet())
|
||||
.add(childKey);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processEvent(@Nonnull String hookName) {
|
||||
HytaleLogger.getLogger()
|
||||
.at(Level.INFO)
|
||||
.log(
|
||||
"Generated %d of %s from %s in %s",
|
||||
this.addedAssets.size(),
|
||||
this.tClass.getSimpleName(),
|
||||
hookName,
|
||||
FormatUtil.nanosToString(System.nanoTime() - this.before)
|
||||
);
|
||||
this.loadedAssets.putAll(this.addedAssets);
|
||||
this.addedAssets.clear();
|
||||
|
||||
for (Entry<K, Set<K>> entry : this.addedAssetChildren.entrySet()) {
|
||||
K parent = entry.getKey();
|
||||
this.assetChildren.computeIfAbsent(parent, kx -> ConcurrentHashMap.newKeySet()).addAll(entry.getValue());
|
||||
}
|
||||
|
||||
this.addedAssetChildren.clear();
|
||||
|
||||
for (Entry<Class<? extends JsonAssetWithMap<?, ?>>, Map<?, Set<K>>> entry : this.addedChildAssetsMap.entrySet()) {
|
||||
Class k = entry.getKey();
|
||||
AssetStore assetStore = AssetRegistry.getAssetStore(k);
|
||||
|
||||
for (Entry<?, Set<K>> childEntry : entry.getValue().entrySet()) {
|
||||
assetStore.addChildAssetReferences(childEntry.getKey(), this.tClass, childEntry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
this.addedChildAssetsMap.clear();
|
||||
this.before = System.nanoTime();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public String toString() {
|
||||
return "GenerateAssetsEvent{tClass=" + this.tClass + ", loadedAssets.size()=" + this.loadedAssets.size() + ", " + super.toString() + "}";
|
||||
}
|
||||
|
||||
public static class ParentReference<P extends JsonAssetWithMap<PK, ?>, PK> {
|
||||
private final Class<P> parentAssetClass;
|
||||
private final PK parentKey;
|
||||
|
||||
public ParentReference(Class<P> parentAssetClass, PK parentKey) {
|
||||
this.parentAssetClass = parentAssetClass;
|
||||
this.parentKey = parentKey;
|
||||
}
|
||||
|
||||
public Class<P> getParentAssetClass() {
|
||||
return this.parentAssetClass;
|
||||
}
|
||||
|
||||
public PK getParentKey() {
|
||||
return this.parentKey;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ParentReference{parentAssetClass=" + this.parentAssetClass + ", parentKey=" + this.parentKey + "}";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package com.hypixel.hytale.assetstore.event;
|
||||
|
||||
import com.hypixel.hytale.assetstore.AssetMap;
|
||||
import com.hypixel.hytale.assetstore.AssetUpdateQuery;
|
||||
import com.hypixel.hytale.assetstore.JsonAsset;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class LoadedAssetsEvent<K, T extends JsonAsset<K>, M extends AssetMap<K, T>> extends AssetsEvent<K, T> {
|
||||
@Nonnull
|
||||
private final Class<T> tClass;
|
||||
@Nonnull
|
||||
private final M assetMap;
|
||||
@Nonnull
|
||||
private final Map<K, T> loadedAssets;
|
||||
private final boolean initial;
|
||||
@Nonnull
|
||||
private final AssetUpdateQuery query;
|
||||
|
||||
public LoadedAssetsEvent(@Nonnull Class<T> tClass, @Nonnull M assetMap, @Nonnull Map<K, T> loadedAssets, boolean initial, @Nonnull AssetUpdateQuery query) {
|
||||
this.tClass = tClass;
|
||||
this.assetMap = assetMap;
|
||||
this.loadedAssets = Collections.unmodifiableMap(loadedAssets);
|
||||
this.initial = initial;
|
||||
this.query = query;
|
||||
}
|
||||
|
||||
public Class<T> getAssetClass() {
|
||||
return this.tClass;
|
||||
}
|
||||
|
||||
public M getAssetMap() {
|
||||
return this.assetMap;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public Map<K, T> getLoadedAssets() {
|
||||
return this.loadedAssets;
|
||||
}
|
||||
|
||||
public boolean isInitial() {
|
||||
return this.initial;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public AssetUpdateQuery getQuery() {
|
||||
return this.query;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public String toString() {
|
||||
return "LoadedAssetsEvent{loadedAssets=" + this.loadedAssets + ", initial=" + this.initial + ", query=" + this.query + "} " + super.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.hypixel.hytale.assetstore.event;
|
||||
|
||||
import com.hypixel.hytale.assetstore.AssetStore;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class RegisterAssetStoreEvent extends AssetStoreEvent<Void> {
|
||||
public RegisterAssetStoreEvent(@Nonnull AssetStore<?, ?, ?> assetStore) {
|
||||
super(assetStore);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.hypixel.hytale.assetstore.event;
|
||||
|
||||
import com.hypixel.hytale.assetstore.AssetStore;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class RemoveAssetStoreEvent extends AssetStoreEvent<Void> {
|
||||
public RemoveAssetStoreEvent(@Nonnull AssetStore<?, ?, ?> assetStore) {
|
||||
super(assetStore);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package com.hypixel.hytale.assetstore.event;
|
||||
|
||||
import com.hypixel.hytale.assetstore.AssetMap;
|
||||
import com.hypixel.hytale.assetstore.JsonAsset;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class RemovedAssetsEvent<K, T extends JsonAsset<K>, M extends AssetMap<K, T>> extends AssetsEvent<K, T> {
|
||||
private final Class<T> tClass;
|
||||
private final M assetMap;
|
||||
@Nonnull
|
||||
private final Set<K> removedAssets;
|
||||
private final boolean replaced;
|
||||
|
||||
public RemovedAssetsEvent(Class<T> tClass, M assetMap, @Nonnull Set<K> removedAssets, boolean replaced) {
|
||||
this.tClass = tClass;
|
||||
this.assetMap = assetMap;
|
||||
this.removedAssets = Collections.unmodifiableSet(removedAssets);
|
||||
this.replaced = replaced;
|
||||
}
|
||||
|
||||
public Class<T> getAssetClass() {
|
||||
return this.tClass;
|
||||
}
|
||||
|
||||
public M getAssetMap() {
|
||||
return this.assetMap;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public Set<K> getRemovedAssets() {
|
||||
return this.removedAssets;
|
||||
}
|
||||
|
||||
public boolean isReplaced() {
|
||||
return this.replaced;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RemovedAssetsEvent{removedAssets=" + this.removedAssets + ", replaced=" + this.replaced + "} " + super.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package com.hypixel.hytale.assetstore.iterator;
|
||||
|
||||
import com.hypixel.hytale.assetstore.AssetMap;
|
||||
import com.hypixel.hytale.assetstore.AssetRegistry;
|
||||
import com.hypixel.hytale.assetstore.AssetStore;
|
||||
import com.hypixel.hytale.assetstore.JsonAsset;
|
||||
import com.hypixel.hytale.assetstore.map.JsonAssetWithMap;
|
||||
import java.io.Closeable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class AssetStoreIterator implements Iterator<AssetStore<?, ?, ?>>, Closeable {
|
||||
@Nonnull
|
||||
private final List<AssetStore<?, ?, ?>> list;
|
||||
|
||||
public AssetStoreIterator(@Nonnull Collection<AssetStore<?, ?, ?>> values) {
|
||||
this.list = new ArrayList<>(values);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return !this.list.isEmpty();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public AssetStore<?, ?, ?> next() {
|
||||
Iterator<AssetStore<?, ?, ?>> iterator = this.list.iterator();
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
AssetStore<?, ? extends JsonAssetWithMap<?, ? extends AssetMap<?, ?>>, ? extends AssetMap<?, ? extends JsonAssetWithMap<?, ?>>> assetStore = (AssetStore<?, ? extends JsonAssetWithMap<?, ? extends AssetMap<?, ?>>, ? extends AssetMap<?, ? extends JsonAssetWithMap<?, ?>>>)iterator.next();
|
||||
if (!this.isWaitingForDependencies(assetStore)) {
|
||||
iterator.remove();
|
||||
return assetStore;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return this.list.size();
|
||||
}
|
||||
|
||||
public boolean isWaitingForDependencies(@Nonnull AssetStore<?, ?, ?> assetStore) {
|
||||
for (Class<? extends JsonAsset<?>> aClass : assetStore.getLoadsAfter()) {
|
||||
AssetStore otherStore = AssetRegistry.getAssetStore(aClass);
|
||||
if (otherStore == null) {
|
||||
throw new IllegalArgumentException("Unable to find asset store: " + aClass);
|
||||
}
|
||||
|
||||
if (this.list.contains(otherStore)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isBeingWaitedFor(@Nonnull AssetStore<?, ?, ?> assetStore) {
|
||||
Class<? extends JsonAssetWithMap<?, ? extends AssetMap<?, ?>>> assetClass = (Class<? extends JsonAssetWithMap<?, ? extends AssetMap<?, ?>>>)assetStore.getAssetClass();
|
||||
|
||||
for (AssetStore<?, ?, ?> store : this.list) {
|
||||
if (store.getLoadsAfter().contains(assetClass)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.hypixel.hytale.assetstore.iterator;
|
||||
|
||||
import com.hypixel.hytale.assetstore.AssetRegistry;
|
||||
import com.hypixel.hytale.assetstore.AssetStore;
|
||||
import com.hypixel.hytale.assetstore.JsonAsset;
|
||||
import java.util.Collection;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class CircularDependencyException extends RuntimeException {
|
||||
public CircularDependencyException(@Nonnull Collection<AssetStore<?, ?, ?>> values, @Nonnull AssetStoreIterator iterator) {
|
||||
super(makeMessage(values, iterator));
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
protected static String makeMessage(@Nonnull Collection<AssetStore<?, ?, ?>> values, @Nonnull AssetStoreIterator iterator) {
|
||||
StringBuilder sb = new StringBuilder(
|
||||
"Failed to process any stores there must be a circular dependency! " + values + ", " + iterator.size() + "\nWaiting for Asset Stores:\n"
|
||||
);
|
||||
|
||||
for (AssetStore<?, ?, ?> store : values) {
|
||||
if (iterator.isWaitingForDependencies(store)) {
|
||||
sb.append(store.getAssetClass()).append("\n");
|
||||
|
||||
for (Class<? extends JsonAsset<?>> aClass : store.getLoadsAfter()) {
|
||||
AssetStore otherStore = AssetRegistry.getAssetStore(aClass);
|
||||
if (otherStore == null) {
|
||||
throw new IllegalArgumentException("Unable to find asset store: " + aClass);
|
||||
}
|
||||
|
||||
if (iterator.isWaitingForDependencies(otherStore)) {
|
||||
sb.append("\t- ").append(otherStore.getAssetClass()).append("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package com.hypixel.hytale.assetstore.map;
|
||||
|
||||
import com.hypixel.fastutil.ints.Int2ObjectConcurrentHashMap;
|
||||
import com.hypixel.hytale.assetstore.AssetExtraInfo;
|
||||
import com.hypixel.hytale.assetstore.JsonAsset;
|
||||
import com.hypixel.hytale.assetstore.codec.AssetCodec;
|
||||
import it.unimi.dsi.fastutil.ints.IntIterator;
|
||||
import it.unimi.dsi.fastutil.ints.IntSet;
|
||||
import it.unimi.dsi.fastutil.ints.IntSets;
|
||||
import java.util.Map;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public abstract class AssetMapWithIndexes<K, T extends JsonAsset<K>> extends DefaultAssetMap<K, T> {
|
||||
public static final int NOT_FOUND = Integer.MIN_VALUE;
|
||||
protected final Int2ObjectConcurrentHashMap<IntSet> indexedTagStorage = new Int2ObjectConcurrentHashMap<>();
|
||||
protected final Int2ObjectConcurrentHashMap<IntSet> unmodifiableIndexedTagStorage = new Int2ObjectConcurrentHashMap<>();
|
||||
|
||||
public AssetMapWithIndexes() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void clear() {
|
||||
super.clear();
|
||||
this.indexedTagStorage.clear();
|
||||
this.unmodifiableIndexedTagStorage.clear();
|
||||
}
|
||||
|
||||
public IntSet getIndexesForTag(int index) {
|
||||
return this.unmodifiableIndexedTagStorage.getOrDefault(index, IntSets.EMPTY_SET);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void putAssetTags(AssetCodec<K, T> codec, Map<K, T> loadedAssets) {
|
||||
}
|
||||
|
||||
protected void putAssetTag(@Nonnull AssetCodec<K, T> codec, K key, int index, T value) {
|
||||
AssetExtraInfo.Data data = codec.getData(value);
|
||||
if (data != null) {
|
||||
IntIterator iterator = data.getExpandedTagIndexes().iterator();
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
int tag = iterator.nextInt();
|
||||
this.putAssetTag(key, index, tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void putAssetTag(K key, int index, int tag) {
|
||||
this.putAssetTag(key, tag);
|
||||
this.indexedTagStorage.computeIfAbsent(tag, k -> {
|
||||
IntSet set = Int2ObjectConcurrentHashMap.newKeySet(3);
|
||||
this.unmodifiableIndexedTagStorage.put(k, IntSets.unmodifiable(set));
|
||||
return set;
|
||||
}).add(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean requireReplaceOnRemove() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user