Introduced crash reports
This commit is contained in:
parent
a425af01d8
commit
c1194b7601
@ -33,7 +33,7 @@ public class ArrayUtil {
|
|||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int lastIndexOf(byte[] array, byte element) {
|
public static int lastIndexOf(byte[] array, byte element) {
|
||||||
for (int i = array.length - 1; i >= 0; --i) {
|
for (int i = array.length - 1; i >= 0; --i) {
|
||||||
if (array[i] == element) {
|
if (array[i] == element) {
|
||||||
@ -42,7 +42,7 @@ public class ArrayUtil {
|
|||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int occurences(byte[] array, byte element) {
|
public static int occurences(byte[] array, byte element) {
|
||||||
int result = 0;
|
int result = 0;
|
||||||
for (int i = 0; i < array.length; ++i) {
|
for (int i = 0; i < array.length; ++i) {
|
||||||
@ -52,7 +52,7 @@ public class ArrayUtil {
|
|||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int hasDuplicates(byte[] array) {
|
public static int hasDuplicates(byte[] array) {
|
||||||
for (int i = 0; i < array.length; ++i) {
|
for (int i = 0; i < array.length; ++i) {
|
||||||
byte a = array[i];
|
byte a = array[i];
|
||||||
@ -62,10 +62,10 @@ public class ArrayUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int firstIndexOf(short[] array, short element) {
|
public static int firstIndexOf(short[] array, short element) {
|
||||||
for (int i = 0; i < array.length; ++i) {
|
for (int i = 0; i < array.length; ++i) {
|
||||||
if (array[i] == element) {
|
if (array[i] == element) {
|
||||||
@ -74,7 +74,7 @@ public class ArrayUtil {
|
|||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int lastIndexOf(short[] array, short element) {
|
public static int lastIndexOf(short[] array, short element) {
|
||||||
for (int i = array.length - 1; i >= 0; --i) {
|
for (int i = array.length - 1; i >= 0; --i) {
|
||||||
if (array[i] == element) {
|
if (array[i] == element) {
|
||||||
@ -83,7 +83,7 @@ public class ArrayUtil {
|
|||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int occurences(short[] array, short element) {
|
public static int occurences(short[] array, short element) {
|
||||||
int result = 0;
|
int result = 0;
|
||||||
for (int i = 0; i < array.length; ++i) {
|
for (int i = 0; i < array.length; ++i) {
|
||||||
@ -93,7 +93,7 @@ public class ArrayUtil {
|
|||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int hasDuplicates(short[] array) {
|
public static int hasDuplicates(short[] array) {
|
||||||
for (int i = 0; i < array.length; ++i) {
|
for (int i = 0; i < array.length; ++i) {
|
||||||
short a = array[i];
|
short a = array[i];
|
||||||
@ -103,10 +103,10 @@ public class ArrayUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int firstIndexOf(int[] array, int element) {
|
public static int firstIndexOf(int[] array, int element) {
|
||||||
for (int i = 0; i < array.length; ++i) {
|
for (int i = 0; i < array.length; ++i) {
|
||||||
if (array[i] == element) {
|
if (array[i] == element) {
|
||||||
@ -115,7 +115,7 @@ public class ArrayUtil {
|
|||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int lastIndexOf(int[] array, int element) {
|
public static int lastIndexOf(int[] array, int element) {
|
||||||
for (int i = array.length - 1; i >= 0; --i) {
|
for (int i = array.length - 1; i >= 0; --i) {
|
||||||
if (array[i] == element) {
|
if (array[i] == element) {
|
||||||
@ -124,7 +124,7 @@ public class ArrayUtil {
|
|||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int occurences(int[] array, int element) {
|
public static int occurences(int[] array, int element) {
|
||||||
int result = 0;
|
int result = 0;
|
||||||
for (int i = 0; i < array.length; ++i) {
|
for (int i = 0; i < array.length; ++i) {
|
||||||
@ -134,7 +134,7 @@ public class ArrayUtil {
|
|||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int hasDuplicates(int[] array) {
|
public static int hasDuplicates(int[] array) {
|
||||||
for (int i = 0; i < array.length; ++i) {
|
for (int i = 0; i < array.length; ++i) {
|
||||||
int a = array[i];
|
int a = array[i];
|
||||||
@ -144,10 +144,10 @@ public class ArrayUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int firstIndexOf(long[] array, long element) {
|
public static int firstIndexOf(long[] array, long element) {
|
||||||
for (int i = 0; i < array.length; ++i) {
|
for (int i = 0; i < array.length; ++i) {
|
||||||
if (array[i] == element) {
|
if (array[i] == element) {
|
||||||
@ -156,7 +156,7 @@ public class ArrayUtil {
|
|||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int lastIndexOf(long[] array, long element) {
|
public static int lastIndexOf(long[] array, long element) {
|
||||||
for (int i = array.length - 1; i >= 0; --i) {
|
for (int i = array.length - 1; i >= 0; --i) {
|
||||||
if (array[i] == element) {
|
if (array[i] == element) {
|
||||||
@ -165,7 +165,7 @@ public class ArrayUtil {
|
|||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int occurences(long[] array, long element) {
|
public static int occurences(long[] array, long element) {
|
||||||
int result = 0;
|
int result = 0;
|
||||||
for (int i = 0; i < array.length; ++i) {
|
for (int i = 0; i < array.length; ++i) {
|
||||||
@ -175,7 +175,7 @@ public class ArrayUtil {
|
|||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int hasDuplicates(long[] array) {
|
public static int hasDuplicates(long[] array) {
|
||||||
for (int i = 0; i < array.length; ++i) {
|
for (int i = 0; i < array.length; ++i) {
|
||||||
long a = array[i];
|
long a = array[i];
|
||||||
@ -185,10 +185,10 @@ public class ArrayUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int firstIndexOf(float[] array, float element) {
|
public static int firstIndexOf(float[] array, float element) {
|
||||||
for (int i = 0; i < array.length; ++i) {
|
for (int i = 0; i < array.length; ++i) {
|
||||||
if (array[i] == element) {
|
if (array[i] == element) {
|
||||||
@ -197,7 +197,7 @@ public class ArrayUtil {
|
|||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int lastIndexOf(float[] array, float element) {
|
public static int lastIndexOf(float[] array, float element) {
|
||||||
for (int i = array.length - 1; i >= 0; --i) {
|
for (int i = array.length - 1; i >= 0; --i) {
|
||||||
if (array[i] == element) {
|
if (array[i] == element) {
|
||||||
@ -206,7 +206,7 @@ public class ArrayUtil {
|
|||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int occurences(float[] array, float element) {
|
public static int occurences(float[] array, float element) {
|
||||||
int result = 0;
|
int result = 0;
|
||||||
for (int i = 0; i < array.length; ++i) {
|
for (int i = 0; i < array.length; ++i) {
|
||||||
@ -216,7 +216,7 @@ public class ArrayUtil {
|
|||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int hasDuplicates(float[] array) {
|
public static int hasDuplicates(float[] array) {
|
||||||
for (int i = 0; i < array.length; ++i) {
|
for (int i = 0; i < array.length; ++i) {
|
||||||
float a = array[i];
|
float a = array[i];
|
||||||
@ -226,7 +226,7 @@ public class ArrayUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -238,7 +238,7 @@ public class ArrayUtil {
|
|||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int lastIndexOf(double[] array, double element) {
|
public static int lastIndexOf(double[] array, double element) {
|
||||||
for (int i = array.length - 1; i >= 0; --i) {
|
for (int i = array.length - 1; i >= 0; --i) {
|
||||||
if (array[i] == element) {
|
if (array[i] == element) {
|
||||||
@ -247,7 +247,7 @@ public class ArrayUtil {
|
|||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int occurences(double[] array, double element) {
|
public static int occurences(double[] array, double element) {
|
||||||
int result = 0;
|
int result = 0;
|
||||||
for (int i = 0; i < array.length; ++i) {
|
for (int i = 0; i < array.length; ++i) {
|
||||||
@ -257,7 +257,7 @@ public class ArrayUtil {
|
|||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int hasDuplicates(double[] array) {
|
public static int hasDuplicates(double[] array) {
|
||||||
for (int i = 0; i < array.length; ++i) {
|
for (int i = 0; i < array.length; ++i) {
|
||||||
double a = array[i];
|
double a = array[i];
|
||||||
@ -267,10 +267,10 @@ public class ArrayUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int firstIndexOf(boolean[] array, boolean element) {
|
public static int firstIndexOf(boolean[] array, boolean element) {
|
||||||
for (int i = 0; i < array.length; ++i) {
|
for (int i = 0; i < array.length; ++i) {
|
||||||
if (array[i] == element) {
|
if (array[i] == element) {
|
||||||
@ -279,7 +279,7 @@ public class ArrayUtil {
|
|||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int lastIndexOf(boolean[] array, boolean element) {
|
public static int lastIndexOf(boolean[] array, boolean element) {
|
||||||
for (int i = array.length - 1; i >= 0; --i) {
|
for (int i = array.length - 1; i >= 0; --i) {
|
||||||
if (array[i] == element) {
|
if (array[i] == element) {
|
||||||
@ -288,7 +288,7 @@ public class ArrayUtil {
|
|||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int occurences(boolean[] array, boolean element) {
|
public static int occurences(boolean[] array, boolean element) {
|
||||||
int result = 0;
|
int result = 0;
|
||||||
for (int i = 0; i < array.length; ++i) {
|
for (int i = 0; i < array.length; ++i) {
|
||||||
@ -298,7 +298,7 @@ public class ArrayUtil {
|
|||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int firstIndexOf(char[] array, char element) {
|
public static int firstIndexOf(char[] array, char element) {
|
||||||
for (int i = 0; i < array.length; ++i) {
|
for (int i = 0; i < array.length; ++i) {
|
||||||
if (array[i] == element) {
|
if (array[i] == element) {
|
||||||
@ -307,7 +307,7 @@ public class ArrayUtil {
|
|||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int lastIndexOf(char[] array, char element) {
|
public static int lastIndexOf(char[] array, char element) {
|
||||||
for (int i = array.length - 1; i >= 0; --i) {
|
for (int i = array.length - 1; i >= 0; --i) {
|
||||||
if (array[i] == element) {
|
if (array[i] == element) {
|
||||||
@ -316,7 +316,7 @@ public class ArrayUtil {
|
|||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int occurences(char[] array, char element) {
|
public static int occurences(char[] array, char element) {
|
||||||
int result = 0;
|
int result = 0;
|
||||||
for (int i = 0; i < array.length; ++i) {
|
for (int i = 0; i < array.length; ++i) {
|
||||||
@ -326,7 +326,7 @@ public class ArrayUtil {
|
|||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int hasDuplicates(char[] array) {
|
public static int hasDuplicates(char[] array) {
|
||||||
for (int i = 0; i < array.length; ++i) {
|
for (int i = 0; i < array.length; ++i) {
|
||||||
char a = array[i];
|
char a = array[i];
|
||||||
@ -336,10 +336,10 @@ public class ArrayUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int firstIndexOf(Object[] array, Object element) {
|
public static int firstIndexOf(Object[] array, Object element) {
|
||||||
for (int i = 0; i < array.length; ++i) {
|
for (int i = 0; i < array.length; ++i) {
|
||||||
if (array[i] == element) {
|
if (array[i] == element) {
|
||||||
@ -348,7 +348,7 @@ public class ArrayUtil {
|
|||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int lastIndexOf(Object[] array, Object element) {
|
public static int lastIndexOf(Object[] array, Object element) {
|
||||||
for (int i = array.length - 1; i >= 0; --i) {
|
for (int i = array.length - 1; i >= 0; --i) {
|
||||||
if (array[i] == element) {
|
if (array[i] == element) {
|
||||||
@ -357,7 +357,7 @@ public class ArrayUtil {
|
|||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int occurences(Object[] array, Object element) {
|
public static int occurences(Object[] array, Object element) {
|
||||||
int result = 0;
|
int result = 0;
|
||||||
for (int i = 0; i < array.length; ++i) {
|
for (int i = 0; i < array.length; ++i) {
|
||||||
@ -367,7 +367,7 @@ public class ArrayUtil {
|
|||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int hasDuplicates(Object[] array) {
|
public static int hasDuplicates(Object[] array) {
|
||||||
for (int i = 0; i < array.length; ++i) {
|
for (int i = 0; i < array.length; ++i) {
|
||||||
Object a = array[i];
|
Object a = array[i];
|
||||||
@ -377,10 +377,10 @@ public class ArrayUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int firstIndexOfEqual(Object[] array, Object element) {
|
public static int firstIndexOfEqual(Object[] array, Object element) {
|
||||||
for (int i = 0; i < array.length; ++i) {
|
for (int i = 0; i < array.length; ++i) {
|
||||||
if (Objects.equals(array[i], element)) {
|
if (Objects.equals(array[i], element)) {
|
||||||
@ -389,7 +389,7 @@ public class ArrayUtil {
|
|||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int lastIndexOfEqual(Object[] array, Object element) {
|
public static int lastIndexOfEqual(Object[] array, Object element) {
|
||||||
for (int i = array.length - 1; i >= 0; --i) {
|
for (int i = array.length - 1; i >= 0; --i) {
|
||||||
if (Objects.equals(array[i], element)) {
|
if (Objects.equals(array[i], element)) {
|
||||||
@ -398,7 +398,7 @@ public class ArrayUtil {
|
|||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int occurencesOfEqual(Object[] array, Object element) {
|
public static int occurencesOfEqual(Object[] array, Object element) {
|
||||||
int result = 0;
|
int result = 0;
|
||||||
for (int i = 0; i < array.length; ++i) {
|
for (int i = 0; i < array.length; ++i) {
|
||||||
@ -408,7 +408,7 @@ public class ArrayUtil {
|
|||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int hasEquals(Object[] array) {
|
public static int hasEquals(Object[] array) {
|
||||||
for (int i = 0; i < array.length; ++i) {
|
for (int i = 0; i < array.length; ++i) {
|
||||||
Object a = array[i];
|
Object a = array[i];
|
||||||
@ -418,10 +418,10 @@ public class ArrayUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static long sum(byte[] array, int start, int length) {
|
public static long sum(byte[] array, int start, int length) {
|
||||||
long s = 0;
|
long s = 0;
|
||||||
length += start;
|
length += start;
|
||||||
@ -430,7 +430,7 @@ public class ArrayUtil {
|
|||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static long sum(short[] array, int start, int length) {
|
public static long sum(short[] array, int start, int length) {
|
||||||
long s = 0;
|
long s = 0;
|
||||||
length += start;
|
length += start;
|
||||||
@ -439,7 +439,7 @@ public class ArrayUtil {
|
|||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static long sum(int[] array, int start, int length) {
|
public static long sum(int[] array, int start, int length) {
|
||||||
long s = 0;
|
long s = 0;
|
||||||
length += start;
|
length += start;
|
||||||
@ -448,7 +448,7 @@ public class ArrayUtil {
|
|||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static long sum(long[] array, int start, int length) {
|
public static long sum(long[] array, int start, int length) {
|
||||||
long s = 0;
|
long s = 0;
|
||||||
length += start;
|
length += start;
|
||||||
@ -457,7 +457,7 @@ public class ArrayUtil {
|
|||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static BigInteger longSum(long[] array, int start, int length) {
|
public static BigInteger longSum(long[] array, int start, int length) {
|
||||||
BigInteger s = BigInteger.ZERO;
|
BigInteger s = BigInteger.ZERO;
|
||||||
length += start;
|
length += start;
|
||||||
@ -466,7 +466,7 @@ public class ArrayUtil {
|
|||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static float sum(float[] array, int start, int length) {
|
public static float sum(float[] array, int start, int length) {
|
||||||
float s = 0;
|
float s = 0;
|
||||||
length += start;
|
length += start;
|
||||||
@ -475,7 +475,7 @@ public class ArrayUtil {
|
|||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static double sum(double[] array, int start, int length) {
|
public static double sum(double[] array, int start, int length) {
|
||||||
double s = 0;
|
double s = 0;
|
||||||
length += start;
|
length += start;
|
||||||
@ -484,7 +484,7 @@ public class ArrayUtil {
|
|||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static long sum(char[] array, int start, int length) {
|
public static long sum(char[] array, int start, int length) {
|
||||||
long s = 0;
|
long s = 0;
|
||||||
length += start;
|
length += start;
|
||||||
@ -493,33 +493,35 @@ public class ArrayUtil {
|
|||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int checkArrayOffsetLength(Object array, int offset, int length) {
|
public static int checkArrayOffsetLength(Object array, int offset, int length) {
|
||||||
int arrayLength = Array.getLength(array);
|
int arrayLength = Array.getLength(array);
|
||||||
|
|
||||||
if (length < 0)
|
if (length < 0)
|
||||||
length = arrayLength;
|
length = arrayLength;
|
||||||
|
|
||||||
int end = offset + length;
|
int end = offset + length;
|
||||||
if (end > arrayLength || offset < 0)
|
if (end > arrayLength || offset < 0)
|
||||||
throw new IllegalArgumentException("Array contains [0; " + arrayLength + "), requested [" + offset + "; " + end + ")");
|
throw new IllegalArgumentException(
|
||||||
|
"Array contains [0; " + arrayLength + "), requested [" + offset + "; " + end + ")");
|
||||||
|
|
||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int checkArrayStartEnd(Object array, int start, int end) {
|
public static int checkArrayStartEnd(Object array, int start, int end) {
|
||||||
int arrayLength = Array.getLength(array);
|
int arrayLength = Array.getLength(array);
|
||||||
|
|
||||||
if (end < 0)
|
if (end < 0)
|
||||||
end = arrayLength;
|
end = arrayLength;
|
||||||
|
|
||||||
if (start > end)
|
if (start > end)
|
||||||
throw new IllegalArgumentException("Start > end: " + start + " > " + end);
|
throw new IllegalArgumentException("Start > end: " + start + " > " + end);
|
||||||
|
|
||||||
if (end > arrayLength || start < 0)
|
if (end > arrayLength || start < 0)
|
||||||
throw new IllegalArgumentException("Array contains [0; " + arrayLength + "), requested [" + start + "; " + end + ")");
|
throw new IllegalArgumentException(
|
||||||
|
"Array contains [0; " + arrayLength + "), requested [" + start + "; " + end + ")");
|
||||||
|
|
||||||
return end;
|
return end;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,7 @@ import ru.windcorp.progressia.client.graphics.font.Typefaces;
|
|||||||
import ru.windcorp.progressia.client.graphics.texture.Atlases;
|
import ru.windcorp.progressia.client.graphics.texture.Atlases;
|
||||||
import ru.windcorp.progressia.client.graphics.world.WorldRenderProgram;
|
import ru.windcorp.progressia.client.graphics.world.WorldRenderProgram;
|
||||||
import ru.windcorp.progressia.common.resource.ResourceManager;
|
import ru.windcorp.progressia.common.resource.ResourceManager;
|
||||||
|
import ru.windcorp.progressia.common.util.crash.CrashReports;
|
||||||
import ru.windcorp.progressia.server.ServerState;
|
import ru.windcorp.progressia.server.ServerState;
|
||||||
import ru.windcorp.progressia.test.TestContent;
|
import ru.windcorp.progressia.test.TestContent;
|
||||||
|
|
||||||
@ -39,8 +40,7 @@ public class ClientProxy implements Proxy {
|
|||||||
RenderTaskQueue.waitAndInvoke(WorldRenderProgram::init);
|
RenderTaskQueue.waitAndInvoke(WorldRenderProgram::init);
|
||||||
RenderTaskQueue.waitAndInvoke(() -> Typefaces.setDefault(GNUUnifontLoader.load(ResourceManager.getResource("assets/unifont-13.0.03.hex.gz"))));
|
RenderTaskQueue.waitAndInvoke(() -> Typefaces.setDefault(GNUUnifontLoader.load(ResourceManager.getResource("assets/unifont-13.0.03.hex.gz"))));
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
// TODO Auto-generated catch block
|
CrashReports.report(e, "ClientProxy failed");
|
||||||
e.printStackTrace();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TestContent.registerContent();
|
TestContent.registerContent();
|
||||||
|
@ -20,7 +20,7 @@ package ru.windcorp.progressia.client;
|
|||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import ru.windcorp.progressia.ProgressiaLauncher;
|
import ru.windcorp.progressia.ProgressiaLauncher;
|
||||||
import ru.windcorp.progressia.common.util.crash.CrashReportGenerator;
|
import ru.windcorp.progressia.common.util.crash.CrashReports;
|
||||||
import ru.windcorp.progressia.common.util.crash.analyzers.OutOfMemoryAnalyzer;
|
import ru.windcorp.progressia.common.util.crash.analyzers.OutOfMemoryAnalyzer;
|
||||||
import ru.windcorp.progressia.common.util.crash.providers.OSContextProvider;
|
import ru.windcorp.progressia.common.util.crash.providers.OSContextProvider;
|
||||||
|
|
||||||
@ -31,17 +31,16 @@ public class ProgressiaClientMain {
|
|||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
logger.info("App started!");
|
logger.info("App started!");
|
||||||
|
|
||||||
CrashReportGenerator.registerProvider(new OSContextProvider());
|
CrashReports.registerProvider(new OSContextProvider());
|
||||||
CrashReportGenerator.registerAnalyzer(new OutOfMemoryAnalyzer());
|
CrashReports.registerAnalyzer(new OutOfMemoryAnalyzer());
|
||||||
try {
|
try {
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
long[] ssdss = new long[1 << 30];
|
long[] ssdss = new long[1 << 30];
|
||||||
} catch (Throwable t)
|
} catch (Throwable t) {
|
||||||
{
|
CrashReports.report(t, "u %s stupid", "vry");
|
||||||
CrashReportGenerator.crash(t, "u %s stupid", "vry");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ProgressiaLauncher.launch(args, new ClientProxy());
|
ProgressiaLauncher.launch(args, new ClientProxy());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -8,12 +8,13 @@ import ru.windcorp.progressia.common.comms.CommsListener;
|
|||||||
import ru.windcorp.progressia.common.comms.packets.Packet;
|
import ru.windcorp.progressia.common.comms.packets.Packet;
|
||||||
import ru.windcorp.progressia.common.comms.packets.PacketSetLocalPlayer;
|
import ru.windcorp.progressia.common.comms.packets.PacketSetLocalPlayer;
|
||||||
import ru.windcorp.progressia.common.comms.packets.PacketWorldChange;
|
import ru.windcorp.progressia.common.comms.packets.PacketWorldChange;
|
||||||
|
import ru.windcorp.progressia.common.util.crash.CrashReports;
|
||||||
import ru.windcorp.progressia.common.world.entity.EntityData;
|
import ru.windcorp.progressia.common.world.entity.EntityData;
|
||||||
import ru.windcorp.progressia.common.world.entity.PacketEntityChange;
|
import ru.windcorp.progressia.common.world.entity.PacketEntityChange;
|
||||||
|
|
||||||
// TODO refactor with no mercy
|
// TODO refactor with no mercy
|
||||||
public class DefaultClientCommsListener implements CommsListener {
|
public class DefaultClientCommsListener implements CommsListener {
|
||||||
|
|
||||||
private final Client client;
|
private final Client client;
|
||||||
|
|
||||||
public DefaultClientCommsListener(Client client) {
|
public DefaultClientCommsListener(Client client) {
|
||||||
@ -41,9 +42,9 @@ public class DefaultClientCommsListener implements CommsListener {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (entity == null) {
|
if (entity == null) {
|
||||||
throw new RuntimeException("");
|
CrashReports.report(null, "Player entity not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
getClient().setLocalPlayer(entity);
|
getClient().setLocalPlayer(entity);
|
||||||
getClient().getCamera().setAnchor(new EntityAnchor(
|
getClient().getCamera().setAnchor(new EntityAnchor(
|
||||||
getClient().getWorld().getEntityRenderable(entity)
|
getClient().getWorld().getEntityRenderable(entity)
|
||||||
@ -58,7 +59,7 @@ public class DefaultClientCommsListener implements CommsListener {
|
|||||||
public void onIOError(IOException reason) {
|
public void onIOError(IOException reason) {
|
||||||
// TODO implement
|
// TODO implement
|
||||||
}
|
}
|
||||||
|
|
||||||
public Client getClient() {
|
public Client getClient() {
|
||||||
return client;
|
return client;
|
||||||
}
|
}
|
||||||
|
@ -24,37 +24,38 @@ import ru.windcorp.progressia.client.graphics.backend.OpenGLObjectTracker;
|
|||||||
import ru.windcorp.progressia.client.graphics.backend.OpenGLObjectTracker.OpenGLDeletable;
|
import ru.windcorp.progressia.client.graphics.backend.OpenGLObjectTracker.OpenGLDeletable;
|
||||||
import ru.windcorp.progressia.client.graphics.backend.shaders.attributes.Attribute;
|
import ru.windcorp.progressia.client.graphics.backend.shaders.attributes.Attribute;
|
||||||
import ru.windcorp.progressia.client.graphics.backend.shaders.uniforms.Uniform;
|
import ru.windcorp.progressia.client.graphics.backend.shaders.uniforms.Uniform;
|
||||||
|
import ru.windcorp.progressia.common.util.crash.CrashReports;
|
||||||
|
|
||||||
public class Program implements OpenGLDeletable {
|
public class Program implements OpenGLDeletable {
|
||||||
|
|
||||||
private int handle;
|
private int handle;
|
||||||
|
|
||||||
public Program(Shader vertexShader, Shader fragmentShader) {
|
public Program(Shader vertexShader, Shader fragmentShader) {
|
||||||
handle = glCreateProgram();
|
handle = glCreateProgram();
|
||||||
OpenGLObjectTracker.register(this);
|
OpenGLObjectTracker.register(this);
|
||||||
|
|
||||||
glAttachShader(handle, vertexShader.getHandle());
|
glAttachShader(handle, vertexShader.getHandle());
|
||||||
glAttachShader(handle, fragmentShader.getHandle());
|
glAttachShader(handle, fragmentShader.getHandle());
|
||||||
|
|
||||||
glLinkProgram(handle);
|
glLinkProgram(handle);
|
||||||
|
|
||||||
if (glGetProgrami(handle, GL_LINK_STATUS) == GL_FALSE) {
|
if (glGetProgrami(handle, GL_LINK_STATUS) == GL_FALSE) {
|
||||||
throw new RuntimeException("Bad program:\n" + glGetProgramInfoLog(handle));
|
CrashReports.report(null, "Bad program:\n %s", glGetProgramInfoLog(handle));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Attribute getAttribute(String name) {
|
public Attribute getAttribute(String name) {
|
||||||
return new Attribute(glGetAttribLocation(handle, name), this);
|
return new Attribute(glGetAttribLocation(handle, name), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Uniform getUniform(String name) {
|
public Uniform getUniform(String name) {
|
||||||
return new Uniform(glGetUniformLocation(handle, name), this);
|
return new Uniform(glGetUniformLocation(handle, name), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void use() {
|
public void use() {
|
||||||
glUseProgram(handle);
|
glUseProgram(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void delete() {
|
public void delete() {
|
||||||
glDeleteProgram(handle);
|
glDeleteProgram(handle);
|
||||||
|
@ -26,26 +26,26 @@ import ru.windcorp.progressia.client.graphics.backend.OpenGLObjectTracker;
|
|||||||
import ru.windcorp.progressia.client.graphics.backend.OpenGLObjectTracker.OpenGLDeletable;
|
import ru.windcorp.progressia.client.graphics.backend.OpenGLObjectTracker.OpenGLDeletable;
|
||||||
import ru.windcorp.progressia.common.resource.Resource;
|
import ru.windcorp.progressia.common.resource.Resource;
|
||||||
import ru.windcorp.progressia.common.resource.ResourceManager;
|
import ru.windcorp.progressia.common.resource.ResourceManager;
|
||||||
|
import ru.windcorp.progressia.common.util.crash.CrashReports;
|
||||||
|
|
||||||
public class Shader implements OpenGLDeletable {
|
public class Shader implements OpenGLDeletable {
|
||||||
|
|
||||||
public static enum ShaderType {
|
public static enum ShaderType {
|
||||||
VERTEX(GL_VERTEX_SHADER),
|
VERTEX(GL_VERTEX_SHADER), FRAGMENT(GL_FRAGMENT_SHADER);
|
||||||
FRAGMENT(GL_FRAGMENT_SHADER);
|
|
||||||
|
|
||||||
private final int glCode;
|
private final int glCode;
|
||||||
|
|
||||||
private ShaderType(int glCode) {
|
private ShaderType(int glCode) {
|
||||||
this.glCode = glCode;
|
this.glCode = glCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getGlCode() {
|
public int getGlCode() {
|
||||||
return glCode;
|
return glCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ShaderType guessByResourceName(String resource) {
|
public static ShaderType guessByResourceName(String resource) {
|
||||||
resource = resource.toLowerCase(Locale.ENGLISH);
|
resource = resource.toLowerCase(Locale.ENGLISH);
|
||||||
|
|
||||||
if (resource.contains("vertex")) return VERTEX;
|
if (resource.contains("vertex")) return VERTEX;
|
||||||
if (resource.contains("fragment")) return FRAGMENT;
|
if (resource.contains("fragment")) return FRAGMENT;
|
||||||
if (resource.contains("vsh")) return VERTEX;
|
if (resource.contains("vsh")) return VERTEX;
|
||||||
@ -57,48 +57,48 @@ public class Shader implements OpenGLDeletable {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final String SHADER_ASSETS_PREFIX = "assets/shaders/";
|
private static final String SHADER_ASSETS_PREFIX = "assets/shaders/";
|
||||||
|
|
||||||
protected static Resource getShaderResource(String name) {
|
protected static Resource getShaderResource(String name) {
|
||||||
return ResourceManager.getResource(SHADER_ASSETS_PREFIX + name);
|
return ResourceManager.getResource(SHADER_ASSETS_PREFIX + name);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final int handle;
|
private final int handle;
|
||||||
private final ShaderType type;
|
private final ShaderType type;
|
||||||
|
|
||||||
public Shader(ShaderType type, String source) {
|
public Shader(ShaderType type, String source) {
|
||||||
handle = glCreateShader(type.getGlCode());
|
handle = glCreateShader(type.getGlCode());
|
||||||
OpenGLObjectTracker.register(this);
|
OpenGLObjectTracker.register(this);
|
||||||
|
|
||||||
this.type = type;
|
this.type = type;
|
||||||
|
|
||||||
glShaderSource(handle, source);
|
glShaderSource(handle, source);
|
||||||
glCompileShader(handle);
|
glCompileShader(handle);
|
||||||
|
|
||||||
if (glGetShaderi(handle, GL_COMPILE_STATUS) == GL_FALSE) {
|
if (glGetShaderi(handle, GL_COMPILE_STATUS) == GL_FALSE) {
|
||||||
System.out.println("***************** ERROR ******************");
|
System.out.println("***************** ERROR ******************");
|
||||||
System.out.println(source);
|
System.out.println(source);
|
||||||
throw new RuntimeException("Bad shader:\n" + glGetShaderInfoLog(handle));
|
CrashReports.report(null, "Bad shader:\n %s", glGetShaderInfoLog(handle));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Shader(String resource) {
|
public Shader(String resource) {
|
||||||
this(
|
this(
|
||||||
ShaderType.guessByResourceName(resource),
|
ShaderType.guessByResourceName(resource),
|
||||||
getShaderResource(resource).readAsString()
|
getShaderResource(resource).readAsString()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void delete() {
|
public void delete() {
|
||||||
glDeleteShader(handle);
|
glDeleteShader(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getHandle() {
|
public int getHandle() {
|
||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ShaderType getType() {
|
public ShaderType getType() {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
@ -18,29 +18,30 @@
|
|||||||
package ru.windcorp.progressia.client.graphics.backend.shaders.attributes;
|
package ru.windcorp.progressia.client.graphics.backend.shaders.attributes;
|
||||||
|
|
||||||
import ru.windcorp.progressia.client.graphics.backend.shaders.Program;
|
import ru.windcorp.progressia.client.graphics.backend.shaders.Program;
|
||||||
|
import ru.windcorp.progressia.common.util.crash.CrashReports;
|
||||||
|
|
||||||
public class Attribute {
|
public class Attribute {
|
||||||
|
|
||||||
protected final int handle;
|
protected final int handle;
|
||||||
private final Program program;
|
private final Program program;
|
||||||
|
|
||||||
public Attribute(int handle, Program program) {
|
public Attribute(int handle, Program program) {
|
||||||
if (handle < 0) {
|
if (handle < 0) {
|
||||||
throw new RuntimeException("Bad handle: " + handle);
|
CrashReports.report(null, "Bad handle: %s", handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.handle = handle;
|
this.handle = handle;
|
||||||
this.program = program;
|
this.program = program;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getHandle() {
|
public int getHandle() {
|
||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Program getProgram() {
|
public Program getProgram() {
|
||||||
return program;
|
return program;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AttributeVertexArray asVertexArray() {
|
public AttributeVertexArray asVertexArray() {
|
||||||
return new AttributeVertexArray(handle, program);
|
return new AttributeVertexArray(handle, program);
|
||||||
}
|
}
|
||||||
|
@ -18,69 +18,70 @@
|
|||||||
package ru.windcorp.progressia.client.graphics.backend.shaders.uniforms;
|
package ru.windcorp.progressia.client.graphics.backend.shaders.uniforms;
|
||||||
|
|
||||||
import ru.windcorp.progressia.client.graphics.backend.shaders.Program;
|
import ru.windcorp.progressia.client.graphics.backend.shaders.Program;
|
||||||
|
import ru.windcorp.progressia.common.util.crash.CrashReports;
|
||||||
|
|
||||||
public class Uniform {
|
public class Uniform {
|
||||||
|
|
||||||
protected final int handle;
|
protected final int handle;
|
||||||
private final Program program;
|
private final Program program;
|
||||||
|
|
||||||
public Uniform(int handle, Program program) {
|
public Uniform(int handle, Program program) {
|
||||||
if (handle < 0) {
|
if (handle < 0) {
|
||||||
throw new RuntimeException("Bad handle: " + handle);
|
CrashReports.report(null, "Bad handle: %s", handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.handle = handle;
|
this.handle = handle;
|
||||||
this.program = program;
|
this.program = program;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getHandle() {
|
public int getHandle() {
|
||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Program getProgram() {
|
public Program getProgram() {
|
||||||
return program;
|
return program;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Uniform1Float as1Float() {
|
public Uniform1Float as1Float() {
|
||||||
return new Uniform1Float(handle, program);
|
return new Uniform1Float(handle, program);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Uniform1Int as1Int() {
|
public Uniform1Int as1Int() {
|
||||||
return new Uniform1Int(handle, program);
|
return new Uniform1Int(handle, program);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Uniform2Float as2Float() {
|
public Uniform2Float as2Float() {
|
||||||
return new Uniform2Float(handle, program);
|
return new Uniform2Float(handle, program);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Uniform2Int as2Int() {
|
public Uniform2Int as2Int() {
|
||||||
return new Uniform2Int(handle, program);
|
return new Uniform2Int(handle, program);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Uniform3Float as3Float() {
|
public Uniform3Float as3Float() {
|
||||||
return new Uniform3Float(handle, program);
|
return new Uniform3Float(handle, program);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Uniform3Int as3Int() {
|
public Uniform3Int as3Int() {
|
||||||
return new Uniform3Int(handle, program);
|
return new Uniform3Int(handle, program);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Uniform4Float as4Float() {
|
public Uniform4Float as4Float() {
|
||||||
return new Uniform4Float(handle, program);
|
return new Uniform4Float(handle, program);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Uniform4Int as4Int() {
|
public Uniform4Int as4Int() {
|
||||||
return new Uniform4Int(handle, program);
|
return new Uniform4Int(handle, program);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Uniform2Matrix as2Matrix() {
|
public Uniform2Matrix as2Matrix() {
|
||||||
return new Uniform2Matrix(handle, program);
|
return new Uniform2Matrix(handle, program);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Uniform3Matrix as3Matrix() {
|
public Uniform3Matrix as3Matrix() {
|
||||||
return new Uniform3Matrix(handle, program);
|
return new Uniform3Matrix(handle, program);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Uniform4Matrix as4Matrix() {
|
public Uniform4Matrix as4Matrix() {
|
||||||
return new Uniform4Matrix(handle, program);
|
return new Uniform4Matrix(handle, program);
|
||||||
}
|
}
|
||||||
|
@ -21,117 +21,96 @@ import ru.windcorp.progressia.client.graphics.texture.Texture;
|
|||||||
import ru.windcorp.progressia.client.graphics.texture.TextureDataEditor;
|
import ru.windcorp.progressia.client.graphics.texture.TextureDataEditor;
|
||||||
import ru.windcorp.progressia.client.graphics.texture.TextureSettings;
|
import ru.windcorp.progressia.client.graphics.texture.TextureSettings;
|
||||||
import ru.windcorp.progressia.common.resource.Resource;
|
import ru.windcorp.progressia.common.resource.Resource;
|
||||||
|
import ru.windcorp.progressia.common.util.crash.CrashReports;
|
||||||
|
|
||||||
public class GNUUnifontLoader {
|
public class GNUUnifontLoader {
|
||||||
|
|
||||||
private static final AtlasGroup ATLAS_GROUP_GNU_UNIFONT =
|
private static final AtlasGroup ATLAS_GROUP_GNU_UNIFONT = new AtlasGroup("GNUUnifont", 1 << 12);
|
||||||
new AtlasGroup("GNUUnifont", 1 << 12);
|
|
||||||
|
private static final TextureSettings TEXTURE_SETTINGS = new TextureSettings(false);
|
||||||
private static final TextureSettings TEXTURE_SETTINGS =
|
|
||||||
new TextureSettings(false);
|
|
||||||
|
|
||||||
private static final int BITS_PER_HEX_DIGIT = 4;
|
private static final int BITS_PER_HEX_DIGIT = 4;
|
||||||
private static final int PREFIX_LENGTH = "0000:".length();
|
private static final int PREFIX_LENGTH = "0000:".length();
|
||||||
|
|
||||||
private static class ParsedGlyph {
|
private static class ParsedGlyph {
|
||||||
final char c;
|
final char c;
|
||||||
final TextureDataEditor data;
|
final TextureDataEditor data;
|
||||||
|
|
||||||
ParsedGlyph(char c, TextureDataEditor data) {
|
ParsedGlyph(char c, TextureDataEditor data) {
|
||||||
this.c = c;
|
this.c = c;
|
||||||
this.data = data;
|
this.data = data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class AtlasGlyph {
|
private static class AtlasGlyph {
|
||||||
final char c;
|
final char c;
|
||||||
final Texture texture;
|
final Texture texture;
|
||||||
|
|
||||||
AtlasGlyph(char c, Texture texture) {
|
AtlasGlyph(char c, Texture texture) {
|
||||||
this.c = c;
|
this.c = c;
|
||||||
this.texture = texture;
|
this.texture = texture;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static GNUUnifont load(Resource resource) {
|
public static GNUUnifont load(Resource resource) {
|
||||||
try (BufferedReader reader = createReader(resource)) {
|
try (BufferedReader reader = createReader(resource)) {
|
||||||
return createStream(reader)
|
return createStream(reader).map(GNUUnifontLoader::parse).map(GNUUnifontLoader::addToAtlas)
|
||||||
.map(GNUUnifontLoader::parse)
|
.collect(Collectors.collectingAndThen(createMapper(), GNUUnifont::new));
|
||||||
.map(GNUUnifontLoader::addToAtlas)
|
|
||||||
.collect(Collectors.collectingAndThen(
|
|
||||||
createMapper(),
|
|
||||||
GNUUnifont::new
|
|
||||||
));
|
|
||||||
} catch (IOException | UncheckedIOException e) {
|
} catch (IOException | UncheckedIOException e) {
|
||||||
throw new RuntimeException(e);
|
CrashReports.report(e, "Problem with load GNUUnifont");
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static BufferedReader createReader(Resource resource)
|
private static BufferedReader createReader(Resource resource) throws IOException {
|
||||||
throws IOException
|
|
||||||
{
|
|
||||||
return new BufferedReader(
|
return new BufferedReader(
|
||||||
new InputStreamReader(
|
new InputStreamReader(new GZIPInputStream(resource.getInputStream()), StandardCharsets.UTF_8));
|
||||||
new GZIPInputStream(
|
|
||||||
resource.getInputStream()
|
|
||||||
),
|
|
||||||
StandardCharsets.UTF_8
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Stream<String> createStream(BufferedReader reader) {
|
private static Stream<String> createStream(BufferedReader reader) {
|
||||||
return reader.lines();
|
return reader.lines();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ParsedGlyph parse(String declar) {
|
private static ParsedGlyph parse(String declar) {
|
||||||
int width = getWidth(declar);
|
int width = getWidth(declar);
|
||||||
checkDeclaration(declar, width);
|
checkDeclaration(declar, width);
|
||||||
|
|
||||||
char c = getChar(declar);
|
char c = getChar(declar);
|
||||||
|
|
||||||
TextureDataEditor editor = new TextureDataEditor(
|
TextureDataEditor editor = new TextureDataEditor(width, GNUUnifont.HEIGHT, width, GNUUnifont.HEIGHT,
|
||||||
width, GNUUnifont.HEIGHT,
|
TEXTURE_SETTINGS);
|
||||||
width, GNUUnifont.HEIGHT,
|
|
||||||
TEXTURE_SETTINGS
|
|
||||||
);
|
|
||||||
|
|
||||||
for (int y = 0; y < GNUUnifont.HEIGHT; ++y) {
|
for (int y = 0; y < GNUUnifont.HEIGHT; ++y) {
|
||||||
for (int x = 0; x < width; ++x) {
|
for (int x = 0; x < width; ++x) {
|
||||||
int bit = x + y * width;
|
int bit = x + y * width;
|
||||||
|
|
||||||
editor.setPixel(
|
editor.setPixel(x, GNUUnifont.HEIGHT - y - 1, getBit(declar, bit) ? 0xFFFFFFFF : 0x00000000);
|
||||||
x, GNUUnifont.HEIGHT - y - 1,
|
|
||||||
getBit(declar, bit) ? 0xFFFFFFFF : 0x00000000
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ParsedGlyph(c, editor);
|
return new ParsedGlyph(c, editor);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static char getChar(String declar) {
|
private static char getChar(String declar) {
|
||||||
int result = 0;
|
int result = 0;
|
||||||
|
|
||||||
for (int i = 0; i < 4; ++i) {
|
for (int i = 0; i < 4; ++i) {
|
||||||
result =
|
result = (result << BITS_PER_HEX_DIGIT) | getHexValue(declar.charAt(i));
|
||||||
(result << BITS_PER_HEX_DIGIT) |
|
|
||||||
getHexValue(declar.charAt(i));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (char) result;
|
return (char) result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean getBit(String declar, int bit) {
|
private static boolean getBit(String declar, int bit) {
|
||||||
int character = PREFIX_LENGTH + (bit / BITS_PER_HEX_DIGIT);
|
int character = PREFIX_LENGTH + (bit / BITS_PER_HEX_DIGIT);
|
||||||
bit = bit % BITS_PER_HEX_DIGIT;
|
bit = bit % BITS_PER_HEX_DIGIT;
|
||||||
|
|
||||||
char c = declar.charAt(character);
|
char c = declar.charAt(character);
|
||||||
int value = getHexValue(c);
|
int value = getHexValue(c);
|
||||||
|
|
||||||
return (value & (1 << (BITS_PER_HEX_DIGIT - bit - 1))) != 0;
|
return (value & (1 << (BITS_PER_HEX_DIGIT - bit - 1))) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int getWidth(String declar) {
|
private static int getWidth(String declar) {
|
||||||
int meaningfulChars = declar.length() - PREFIX_LENGTH;
|
int meaningfulChars = declar.length() - PREFIX_LENGTH;
|
||||||
final int charsPerColumn = GNUUnifont.HEIGHT / BITS_PER_HEX_DIGIT;
|
final int charsPerColumn = GNUUnifont.HEIGHT / BITS_PER_HEX_DIGIT;
|
||||||
@ -140,33 +119,38 @@ public class GNUUnifontLoader {
|
|||||||
|
|
||||||
private static void checkDeclaration(String declar, int width) {
|
private static void checkDeclaration(String declar, int width) {
|
||||||
if (!GNUUnifont.WIDTHS.contains(width)) {
|
if (!GNUUnifont.WIDTHS.contains(width)) {
|
||||||
throw new RuntimeException("Width " + width + " is not supported (in declar \"" + declar + "\")");
|
CrashReports.report(null, "Width %d is not supported (in declar \"%s\")", width, declar);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((declar.length() - PREFIX_LENGTH) % width != 0) {
|
if ((declar.length() - PREFIX_LENGTH) % width != 0) {
|
||||||
throw new RuntimeException("Declar \"" + declar + "\" has invalid length");
|
CrashReports.report(null, "Declar \"%s\" has invalid length", declar);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < declar.length(); ++i) {
|
for (int i = 0; i < declar.length(); ++i) {
|
||||||
if (i == BITS_PER_HEX_DIGIT) {
|
if (i == BITS_PER_HEX_DIGIT) {
|
||||||
if (declar.charAt(i) != ':') {
|
if (declar.charAt(i) != ':') {
|
||||||
throw new RuntimeException("No colon ':' found in declar \"" + declar + "\" at index 4");
|
CrashReports.report(null, "No colon ':' found in declar \"%s\" at index 4", declar);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
char c = declar.charAt(i);
|
char c = declar.charAt(i);
|
||||||
|
|
||||||
if (!((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F'))) {
|
if (!((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F'))) {
|
||||||
throw new RuntimeException("Illegal char in declar \"" + declar + "\" at index " + i + "; expected 0-9A-F");
|
CrashReports.report(null,
|
||||||
|
"Illegal char in declar \"%s\" at index " + i + "; expected 0-9A-F", declar);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int getHexValue(char digit) {
|
private static int getHexValue(char digit) {
|
||||||
if (digit < '0') throw new NumberFormatException(digit + " is not a hex digit (0-9A-F expected)");
|
if (digit < '0')
|
||||||
if (digit <= '9') return digit - '0';
|
throw new NumberFormatException(digit + " is not a hex digit (0-9A-F expected)");
|
||||||
if (digit < 'A') throw new NumberFormatException(digit + " is not a hex digit (0-9A-F expected)");
|
if (digit <= '9')
|
||||||
if (digit <= 'F') return digit - 'A' + 0xA;
|
return digit - '0';
|
||||||
|
if (digit < 'A')
|
||||||
|
throw new NumberFormatException(digit + " is not a hex digit (0-9A-F expected)");
|
||||||
|
if (digit <= 'F')
|
||||||
|
return digit - 'A' + 0xA;
|
||||||
throw new NumberFormatException(digit + " is not a hex digit (0-9A-F expected)");
|
throw new NumberFormatException(digit + " is not a hex digit (0-9A-F expected)");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,24 +158,21 @@ public class GNUUnifontLoader {
|
|||||||
Sprite sprite = Atlases.loadSprite(glyph.data.getData(), ATLAS_GROUP_GNU_UNIFONT);
|
Sprite sprite = Atlases.loadSprite(glyph.data.getData(), ATLAS_GROUP_GNU_UNIFONT);
|
||||||
return new AtlasGlyph(glyph.c, new SimpleTexture(sprite));
|
return new AtlasGlyph(glyph.c, new SimpleTexture(sprite));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static
|
private static Collector<AtlasGlyph, ?, TCharObjectMap<Texture>> createMapper() {
|
||||||
Collector<AtlasGlyph, ?, TCharObjectMap<Texture>>
|
return Collector.of(TCharObjectHashMap<Texture>::new,
|
||||||
createMapper() {
|
|
||||||
return Collector.of(
|
|
||||||
TCharObjectHashMap<Texture>::new,
|
|
||||||
|
|
||||||
(map, glyph) -> map.put(glyph.c, glyph.texture),
|
(map, glyph) -> map.put(glyph.c, glyph.texture),
|
||||||
|
|
||||||
(a, b) -> {
|
(a, b) -> {
|
||||||
a.putAll(b);
|
a.putAll(b);
|
||||||
return a;
|
return a;
|
||||||
},
|
},
|
||||||
|
|
||||||
Characteristics.UNORDERED
|
Characteristics.UNORDERED);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private GNUUnifontLoader() {}
|
private GNUUnifontLoader() {
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -39,40 +39,40 @@ import ru.windcorp.progressia.client.graphics.input.bus.Input;
|
|||||||
import ru.windcorp.progressia.client.graphics.input.bus.InputBus;
|
import ru.windcorp.progressia.client.graphics.input.bus.InputBus;
|
||||||
import ru.windcorp.progressia.client.graphics.input.bus.InputListener;
|
import ru.windcorp.progressia.client.graphics.input.bus.InputListener;
|
||||||
import ru.windcorp.progressia.common.util.Named;
|
import ru.windcorp.progressia.common.util.Named;
|
||||||
|
import ru.windcorp.progressia.common.util.crash.CrashReports;
|
||||||
|
|
||||||
public class Component extends Named {
|
public class Component extends Named {
|
||||||
|
|
||||||
private final List<Component> children =
|
private final List<Component> children = Collections.synchronizedList(new CopyOnWriteArrayList<>());
|
||||||
Collections.synchronizedList(new CopyOnWriteArrayList<>());
|
|
||||||
|
|
||||||
private Component parent = null;
|
private Component parent = null;
|
||||||
|
|
||||||
private EventBus eventBus = null;
|
private EventBus eventBus = null;
|
||||||
private InputBus inputBus = null;
|
private InputBus inputBus = null;
|
||||||
|
|
||||||
private int x, y;
|
private int x, y;
|
||||||
private int width, height;
|
private int width, height;
|
||||||
|
|
||||||
private boolean valid = false;
|
private boolean valid = false;
|
||||||
|
|
||||||
private Vec2i preferredSize = null;
|
private Vec2i preferredSize = null;
|
||||||
|
|
||||||
private Object layoutHint = null;
|
private Object layoutHint = null;
|
||||||
private Layout layout = null;
|
private Layout layout = null;
|
||||||
|
|
||||||
private boolean isFocusable = false;
|
private boolean isFocusable = false;
|
||||||
private boolean isFocused = false;
|
private boolean isFocused = false;
|
||||||
|
|
||||||
private boolean isHovered = false;
|
private boolean isHovered = false;
|
||||||
|
|
||||||
public Component(String name) {
|
public Component(String name) {
|
||||||
super(name);
|
super(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Component getParent() {
|
public Component getParent() {
|
||||||
return parent;
|
return parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setParent(Component parent) {
|
protected void setParent(Component parent) {
|
||||||
if (this.parent != parent) {
|
if (this.parent != parent) {
|
||||||
Component previousParent = this.parent;
|
Component previousParent = this.parent;
|
||||||
@ -81,68 +81,71 @@ public class Component extends Named {
|
|||||||
dispatchEvent(new ParentChangedEvent(this, previousParent, parent));
|
dispatchEvent(new ParentChangedEvent(this, previousParent, parent));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Component> getChildren() {
|
public List<Component> getChildren() {
|
||||||
return children;
|
return children;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Component getChild(int index) {
|
public Component getChild(int index) {
|
||||||
synchronized (getChildren()) {
|
synchronized (getChildren()) {
|
||||||
if (index < 0 || index >= getChildren().size()) return null;
|
if (index < 0 || index >= getChildren().size())
|
||||||
|
return null;
|
||||||
return getChildren().get(index);
|
return getChildren().get(index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getChildIndex(Component child) {
|
public int getChildIndex(Component child) {
|
||||||
return getChildren().indexOf(child);
|
return getChildren().indexOf(child);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getOwnIndex() {
|
public int getOwnIndex() {
|
||||||
Component parent = getParent();
|
Component parent = getParent();
|
||||||
if (parent != null) {
|
if (parent != null) {
|
||||||
return parent.getChildIndex(this);
|
return parent.getChildIndex(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void moveChild(Component child, int newIndex) {
|
public void moveChild(Component child, int newIndex) {
|
||||||
if (newIndex == -1) newIndex = getChildren().size() - 1;
|
if (newIndex == -1)
|
||||||
|
newIndex = getChildren().size() - 1;
|
||||||
|
|
||||||
if (getChildren().remove(child)) {
|
if (getChildren().remove(child)) {
|
||||||
getChildren().add(newIndex, child);
|
getChildren().add(newIndex, child);
|
||||||
invalidate();
|
invalidate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void moveSelf(int newIndex) {
|
public void moveSelf(int newIndex) {
|
||||||
Component parent = getParent();
|
Component parent = getParent();
|
||||||
if (parent != null) {
|
if (parent != null) {
|
||||||
parent.moveChild(this, newIndex);
|
parent.moveChild(this, newIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Component addChild(Component child, int index) {
|
public Component addChild(Component child, int index) {
|
||||||
if (index == -1) index = getChildren().size();
|
if (index == -1)
|
||||||
|
index = getChildren().size();
|
||||||
|
|
||||||
invalidate();
|
invalidate();
|
||||||
getChildren().add(index, child);
|
getChildren().add(index, child);
|
||||||
child.setParent(this);
|
child.setParent(this);
|
||||||
|
|
||||||
dispatchEvent(new ChildAddedEvent(this, child));
|
dispatchEvent(new ChildAddedEvent(this, child));
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Component addChild(Component child) {
|
public Component addChild(Component child) {
|
||||||
return addChild(child, -1);
|
return addChild(child, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Component removeChild(Component child) {
|
public Component removeChild(Component child) {
|
||||||
if (!getChildren().contains(child)) {
|
if (!getChildren().contains(child)) {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (child.isFocused()) {
|
if (child.isFocused()) {
|
||||||
child.focusNext();
|
child.focusNext();
|
||||||
}
|
}
|
||||||
@ -150,204 +153,205 @@ public class Component extends Named {
|
|||||||
invalidate();
|
invalidate();
|
||||||
getChildren().remove(child);
|
getChildren().remove(child);
|
||||||
child.setParent(null);
|
child.setParent(null);
|
||||||
|
|
||||||
dispatchEvent(new ChildRemovedEvent(this, child));
|
dispatchEvent(new ChildRemovedEvent(this, child));
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized int getX() {
|
public synchronized int getX() {
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized int getY() {
|
public synchronized int getY() {
|
||||||
return y;
|
return y;
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized Component setPosition(int x, int y) {
|
public synchronized Component setPosition(int x, int y) {
|
||||||
invalidate();
|
invalidate();
|
||||||
this.x = x;
|
this.x = x;
|
||||||
this.y = y;
|
this.y = y;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized int getWidth() {
|
public synchronized int getWidth() {
|
||||||
return width;
|
return width;
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized int getHeight() {
|
public synchronized int getHeight() {
|
||||||
return height;
|
return height;
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized Component setSize(int width, int height) {
|
public synchronized Component setSize(int width, int height) {
|
||||||
invalidate();
|
invalidate();
|
||||||
this.width = width;
|
this.width = width;
|
||||||
this.height = height;
|
this.height = height;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Component setSize(Vec2i size) {
|
public Component setSize(Vec2i size) {
|
||||||
return setSize(size.x, size.y);
|
return setSize(size.x, size.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized Component setBounds(int x, int y, int width, int height) {
|
public synchronized Component setBounds(int x, int y, int width, int height) {
|
||||||
setPosition(x, y);
|
setPosition(x, y);
|
||||||
setSize(width, height);
|
setSize(width, height);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Component setBounds(int x, int y, Vec2i size) {
|
public Component setBounds(int x, int y, Vec2i size) {
|
||||||
return setBounds(x, y, size.x, size.y);
|
return setBounds(x, y, size.x, size.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isValid() {
|
public boolean isValid() {
|
||||||
return valid;
|
return valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void invalidate() {
|
public synchronized void invalidate() {
|
||||||
valid = false;
|
valid = false;
|
||||||
getChildren().forEach(child -> child.invalidate());
|
getChildren().forEach(child -> child.invalidate());
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void validate() {
|
public synchronized void validate() {
|
||||||
Component parent = getParent();
|
Component parent = getParent();
|
||||||
invalidate();
|
invalidate();
|
||||||
|
|
||||||
if (parent == null) {
|
if (parent == null) {
|
||||||
layoutSelf();
|
layoutSelf();
|
||||||
} else {
|
} else {
|
||||||
parent.validate();
|
parent.validate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected synchronized void layoutSelf() {
|
protected synchronized void layoutSelf() {
|
||||||
try {
|
try {
|
||||||
if (getLayout() != null) {
|
if (getLayout() != null) {
|
||||||
getLayout().layout(this);
|
getLayout().layout(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
getChildren().forEach(child -> {
|
getChildren().forEach(child -> {
|
||||||
child.layoutSelf();
|
child.layoutSelf();
|
||||||
});
|
});
|
||||||
|
|
||||||
valid = true;
|
valid = true;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException(e);
|
CrashReports.report(e, "__DOC__ME__");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized Vec2i getPreferredSize() {
|
public synchronized Vec2i getPreferredSize() {
|
||||||
if (preferredSize != null) {
|
if (preferredSize != null) {
|
||||||
return preferredSize;
|
return preferredSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getLayout() != null) {
|
if (getLayout() != null) {
|
||||||
try {
|
try {
|
||||||
return getLayout().calculatePreferredSize(this);
|
return getLayout().calculatePreferredSize(this);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException(e);
|
CrashReports.report(e, "__DOC__ME__");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Vec2i(0, 0);
|
return new Vec2i(0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized Component setPreferredSize(Vec2i preferredSize) {
|
public synchronized Component setPreferredSize(Vec2i preferredSize) {
|
||||||
this.preferredSize = preferredSize;
|
this.preferredSize = preferredSize;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Component setPreferredSize(int width, int height) {
|
public Component setPreferredSize(int width, int height) {
|
||||||
return setPreferredSize(new Vec2i(width, height));
|
return setPreferredSize(new Vec2i(width, height));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Layout getLayout() {
|
public Layout getLayout() {
|
||||||
return layout;
|
return layout;
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized Component setLayout(Layout layout) {
|
public synchronized Component setLayout(Layout layout) {
|
||||||
invalidate();
|
invalidate();
|
||||||
this.layout = layout;
|
this.layout = layout;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object getLayoutHint() {
|
public Object getLayoutHint() {
|
||||||
return layoutHint;
|
return layoutHint;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Component setLayoutHint(Object hint) {
|
public Component setLayoutHint(Object hint) {
|
||||||
this.layoutHint = hint;
|
this.layoutHint = hint;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isFocusable() {
|
public boolean isFocusable() {
|
||||||
return isFocusable;
|
return isFocusable;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Component setFocusable(boolean focusable) {
|
public Component setFocusable(boolean focusable) {
|
||||||
this.isFocusable = focusable;
|
this.isFocusable = focusable;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isFocused() {
|
public boolean isFocused() {
|
||||||
return isFocused;
|
return isFocused;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected synchronized void setFocused(boolean focus) {
|
protected synchronized void setFocused(boolean focus) {
|
||||||
if (focus != this.isFocused) {
|
if (focus != this.isFocused) {
|
||||||
dispatchEvent(new FocusEvent(this, focus));
|
dispatchEvent(new FocusEvent(this, focus));
|
||||||
this.isFocused = focus;
|
this.isFocused = focus;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Component takeFocus() {
|
public Component takeFocus() {
|
||||||
if (isFocused()) {
|
if (isFocused()) {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Component comp = this;
|
Component comp = this;
|
||||||
Component focused = null;
|
Component focused = null;
|
||||||
|
|
||||||
while (comp != null) {
|
while (comp != null) {
|
||||||
if ((focused = comp.findFocused()) != null) {
|
if ((focused = comp.findFocused()) != null) {
|
||||||
focused.setFocused(false);
|
focused.setFocused(false);
|
||||||
setFocused(true);
|
setFocused(true);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
comp = comp.getParent();
|
comp = comp.getParent();
|
||||||
}
|
}
|
||||||
|
|
||||||
setFocused(true);
|
setFocused(true);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void focusNext() {
|
public void focusNext() {
|
||||||
Component component = this;
|
Component component = this;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
|
|
||||||
component = component.getNextFocusCandidate(true);
|
component = component.getNextFocusCandidate(true);
|
||||||
if (component == this) {
|
if (component == this) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (component.isFocusable()) {
|
if (component.isFocusable()) {
|
||||||
setFocused(false);
|
setFocused(false);
|
||||||
component.setFocused(true);
|
component.setFocused(true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Component getNextFocusCandidate(boolean canUseChildren) {
|
private Component getNextFocusCandidate(boolean canUseChildren) {
|
||||||
if (canUseChildren) synchronized (getChildren()) {
|
if (canUseChildren)
|
||||||
if (!getChildren().isEmpty()) {
|
synchronized (getChildren()) {
|
||||||
return getChild(0);
|
if (!getChildren().isEmpty()) {
|
||||||
|
return getChild(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Component parent = getParent();
|
Component parent = getParent();
|
||||||
if (parent != null) {
|
if (parent != null) {
|
||||||
synchronized (parent.getChildren()) {
|
synchronized (parent.getChildren()) {
|
||||||
@ -356,32 +360,32 @@ public class Component extends Named {
|
|||||||
return parent.getChild(ownIndex + 1);
|
return parent.getChild(ownIndex + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return parent.getNextFocusCandidate(false);
|
return parent.getNextFocusCandidate(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void focusPrevious() {
|
public void focusPrevious() {
|
||||||
Component component = this;
|
Component component = this;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
|
|
||||||
component = component.getPreviousFocusCandidate();
|
component = component.getPreviousFocusCandidate();
|
||||||
if (component == this) {
|
if (component == this) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (component.isFocusable()) {
|
if (component.isFocusable()) {
|
||||||
setFocused(false);
|
setFocused(false);
|
||||||
component.setFocused(true);
|
component.setFocused(true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Component getPreviousFocusCandidate() {
|
private Component getPreviousFocusCandidate() {
|
||||||
Component parent = getParent();
|
Component parent = getParent();
|
||||||
if (parent != null) {
|
if (parent != null) {
|
||||||
@ -391,30 +395,30 @@ public class Component extends Named {
|
|||||||
return parent.getChild(ownIndex - 1).getLastDeepChild();
|
return parent.getChild(ownIndex - 1).getLastDeepChild();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return parent;
|
return parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
return getLastDeepChild();
|
return getLastDeepChild();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Component getLastDeepChild() {
|
private Component getLastDeepChild() {
|
||||||
synchronized (getChildren()) {
|
synchronized (getChildren()) {
|
||||||
if (!getChildren().isEmpty()) {
|
if (!getChildren().isEmpty()) {
|
||||||
return getChild(getChildren().size() - 1).getLastDeepChild();
|
return getChild(getChildren().size() - 1).getLastDeepChild();
|
||||||
}
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized Component findFocused() {
|
public synchronized Component findFocused() {
|
||||||
if (isFocused()) {
|
if (isFocused()) {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Component result;
|
Component result;
|
||||||
|
|
||||||
synchronized (getChildren()) {
|
synchronized (getChildren()) {
|
||||||
for (Component c : getChildren()) {
|
for (Component c : getChildren()) {
|
||||||
result = c.findFocused();
|
result = c.findFocused();
|
||||||
@ -423,10 +427,10 @@ public class Component extends Named {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isHovered() {
|
public boolean isHovered() {
|
||||||
return isHovered;
|
return isHovered;
|
||||||
}
|
}
|
||||||
@ -434,9 +438,9 @@ public class Component extends Named {
|
|||||||
protected void setHovered(boolean isHovered) {
|
protected void setHovered(boolean isHovered) {
|
||||||
if (this.isHovered != isHovered) {
|
if (this.isHovered != isHovered) {
|
||||||
this.isHovered = isHovered;
|
this.isHovered = isHovered;
|
||||||
|
|
||||||
if (!isHovered && !getChildren().isEmpty()) {
|
if (!isHovered && !getChildren().isEmpty()) {
|
||||||
|
|
||||||
getChildren().forEach(child -> {
|
getChildren().forEach(child -> {
|
||||||
if (child.isHovered()) {
|
if (child.isHovered()) {
|
||||||
child.setHovered(false);
|
child.setHovered(false);
|
||||||
@ -444,7 +448,7 @@ public class Component extends Named {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatchEvent(new HoverEvent(this, isHovered));
|
dispatchEvent(new HoverEvent(this, isHovered));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -453,40 +457,36 @@ public class Component extends Named {
|
|||||||
if (eventBus == null) {
|
if (eventBus == null) {
|
||||||
eventBus = new EventBus(getName());
|
eventBus = new EventBus(getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
eventBus.register(listener);
|
eventBus.register(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeListener(Object listener) {
|
public void removeListener(Object listener) {
|
||||||
if (eventBus == null) return;
|
if (eventBus == null)
|
||||||
|
return;
|
||||||
eventBus.unregister(listener);
|
eventBus.unregister(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void dispatchEvent(Object event) {
|
public void dispatchEvent(Object event) {
|
||||||
if (eventBus == null) return;
|
if (eventBus == null)
|
||||||
|
return;
|
||||||
eventBus.post(event);
|
eventBus.post(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T extends InputEvent> void addListener(
|
public <T extends InputEvent> void addListener(Class<? extends T> type, boolean handlesConsumed,
|
||||||
Class<? extends T> type,
|
InputListener<T> listener) {
|
||||||
boolean handlesConsumed,
|
|
||||||
InputListener<T> listener
|
|
||||||
) {
|
|
||||||
if (inputBus == null) {
|
if (inputBus == null) {
|
||||||
inputBus = new InputBus();
|
inputBus = new InputBus();
|
||||||
}
|
}
|
||||||
|
|
||||||
inputBus.register(type, handlesConsumed, listener);
|
inputBus.register(type, handlesConsumed, listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T extends InputEvent> void addListener(
|
public <T extends InputEvent> void addListener(Class<? extends T> type, InputListener<T> listener) {
|
||||||
Class<? extends T> type,
|
|
||||||
InputListener<T> listener
|
|
||||||
) {
|
|
||||||
if (inputBus == null) {
|
if (inputBus == null) {
|
||||||
inputBus = new InputBus();
|
inputBus = new InputBus();
|
||||||
}
|
}
|
||||||
|
|
||||||
inputBus.register(type, listener);
|
inputBus.register(type, listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -501,43 +501,45 @@ public class Component extends Named {
|
|||||||
inputBus.dispatch(input);
|
inputBus.dispatch(input);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void dispatchInput(Input input) {
|
public void dispatchInput(Input input) {
|
||||||
try {
|
try {
|
||||||
switch (input.getTarget()) {
|
switch (input.getTarget()) {
|
||||||
case FOCUSED:
|
case FOCUSED:
|
||||||
dispatchInputToFocused(input);
|
dispatchInputToFocused(input);
|
||||||
break;
|
break;
|
||||||
case HOVERED:
|
case HOVERED:
|
||||||
dispatchInputToHovered(input);
|
dispatchInputToHovered(input);
|
||||||
break;
|
break;
|
||||||
case ALL:
|
case ALL:
|
||||||
default:
|
default:
|
||||||
dispatchInputToAll(input);
|
dispatchInputToAll(input);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException(e);
|
CrashReports.report(e, "__DOC__ME__");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void dispatchInputToFocused(Input input) {
|
private void dispatchInputToFocused(Input input) {
|
||||||
Component c = findFocused();
|
Component c = findFocused();
|
||||||
|
|
||||||
if (c == null) return;
|
if (c == null)
|
||||||
if (attemptFocusTransfer(input, c)) return;
|
return;
|
||||||
|
if (attemptFocusTransfer(input, c))
|
||||||
|
return;
|
||||||
|
|
||||||
while (c != null) {
|
while (c != null) {
|
||||||
c.handleInput(input);
|
c.handleInput(input);
|
||||||
c = c.getParent();
|
c = c.getParent();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void dispatchInputToHovered(Input input) {
|
private void dispatchInputToHovered(Input input) {
|
||||||
getChildren().forEach(child -> {
|
getChildren().forEach(child -> {
|
||||||
if (child.containsCursor()) {
|
if (child.containsCursor()) {
|
||||||
child.setHovered(true);
|
child.setHovered(true);
|
||||||
|
|
||||||
if (!input.isConsumed()) {
|
if (!input.isConsumed()) {
|
||||||
child.dispatchInput(input);
|
child.dispatchInput(input);
|
||||||
}
|
}
|
||||||
@ -555,11 +557,13 @@ public class Component extends Named {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean attemptFocusTransfer(Input input, Component focused) {
|
private boolean attemptFocusTransfer(Input input, Component focused) {
|
||||||
if (input.isConsumed()) return false;
|
if (input.isConsumed())
|
||||||
if (!(input.getEvent() instanceof KeyEvent)) return false;
|
return false;
|
||||||
|
if (!(input.getEvent() instanceof KeyEvent))
|
||||||
|
return false;
|
||||||
|
|
||||||
KeyEvent keyInput = (KeyEvent) input.getEvent();
|
KeyEvent keyInput = (KeyEvent) input.getEvent();
|
||||||
|
|
||||||
if (keyInput.getKey() == GLFW.GLFW_KEY_TAB && !keyInput.isRelease()) {
|
if (keyInput.getKey() == GLFW.GLFW_KEY_TAB && !keyInput.isRelease()) {
|
||||||
input.consume();
|
input.consume();
|
||||||
if (keyInput.hasShift()) {
|
if (keyInput.hasShift()) {
|
||||||
@ -569,23 +573,18 @@ public class Component extends Named {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized boolean contains(int x, int y) {
|
public synchronized boolean contains(int x, int y) {
|
||||||
return
|
return x >= getX() && x < getX() + getWidth() && y >= getY() && y < getY() + getHeight();
|
||||||
x >= getX() && x < getX() + getWidth() &&
|
|
||||||
y >= getY() && y < getY() + getHeight();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean containsCursor() {
|
public boolean containsCursor() {
|
||||||
return contains(
|
return contains((int) InputTracker.getCursorX(), (int) InputTracker.getCursorY());
|
||||||
(int) InputTracker.getCursorX(),
|
|
||||||
(int) InputTracker.getCursorY()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void requestReassembly() {
|
public void requestReassembly() {
|
||||||
if (parent != null) {
|
if (parent != null) {
|
||||||
parent.requestReassembly();
|
parent.requestReassembly();
|
||||||
@ -602,60 +601,60 @@ public class Component extends Named {
|
|||||||
if (width == 0 || height == 0) {
|
if (width == 0 || height == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isValid()) {
|
if (!isValid()) {
|
||||||
validate();
|
validate();
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
assembleSelf(target);
|
assembleSelf(target);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException(e);
|
CrashReports.report(e, "__DOC__ME__");
|
||||||
}
|
}
|
||||||
|
|
||||||
assembleChildren(target);
|
assembleChildren(target);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
postAssembleSelf(target);
|
postAssembleSelf(target);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException(e);
|
CrashReports.report(e, "__DOC__ME__");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void assembleSelf(RenderTarget target) {
|
protected void assembleSelf(RenderTarget target) {
|
||||||
// To be overridden
|
// To be overridden
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void postAssembleSelf(RenderTarget target) {
|
protected void postAssembleSelf(RenderTarget target) {
|
||||||
// To be overridden
|
// To be overridden
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void assembleChildren(RenderTarget target) {
|
protected void assembleChildren(RenderTarget target) {
|
||||||
getChildren().forEach(child -> child.assemble(target));
|
getChildren().forEach(child -> child.assemble(target));
|
||||||
}
|
}
|
||||||
|
|
||||||
// /**
|
// /**
|
||||||
// * Returns a component that displays this component in its center.
|
// * Returns a component that displays this component in its center.
|
||||||
// * @return a {@link Aligner} initialized to center this component
|
// * @return a {@link Aligner} initialized to center this component
|
||||||
// */
|
// */
|
||||||
// public Component center() {
|
// public Component center() {
|
||||||
// return new Aligner(this);
|
// return new Aligner(this);
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// /**
|
// /**
|
||||||
// * Returns a component that aligns this component.
|
// * Returns a component that aligns this component.
|
||||||
// * @return a {@link Aligner} initialized with this component
|
// * @return a {@link Aligner} initialized with this component
|
||||||
// */
|
// */
|
||||||
// public Component align(double x, double y) {
|
// public Component align(double x, double y) {
|
||||||
// return new Aligner(this, x, y);
|
// return new Aligner(this, x, y);
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// /**
|
// /**
|
||||||
// * Returns a component that allows scrolling this component
|
// * Returns a component that allows scrolling this component
|
||||||
// * @return a {@link Scroller} initialized with this component
|
// * @return a {@link Scroller} initialized with this component
|
||||||
// */
|
// */
|
||||||
// public Component scroller() {
|
// public Component scroller() {
|
||||||
// return new Scroller(this);
|
// return new Scroller(this);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
}
|
}
|
@ -31,108 +31,101 @@ import gnu.trove.map.hash.TIntObjectHashMap;
|
|||||||
import gnu.trove.map.hash.TObjectIntHashMap;
|
import gnu.trove.map.hash.TObjectIntHashMap;
|
||||||
import gnu.trove.set.TIntSet;
|
import gnu.trove.set.TIntSet;
|
||||||
import gnu.trove.set.hash.TIntHashSet;
|
import gnu.trove.set.hash.TIntHashSet;
|
||||||
|
import ru.windcorp.progressia.common.util.crash.CrashReports;
|
||||||
|
|
||||||
public class Keys {
|
public class Keys {
|
||||||
|
|
||||||
private static final TIntObjectMap<String> CODES_TO_NAMES =
|
private static final TIntObjectMap<String> CODES_TO_NAMES = new TIntObjectHashMap<>();
|
||||||
new TIntObjectHashMap<>();
|
|
||||||
|
private static final TObjectIntMap<String> NAMES_TO_CODES = new TObjectIntHashMap<>();
|
||||||
private static final TObjectIntMap<String> NAMES_TO_CODES =
|
|
||||||
new TObjectIntHashMap<>();
|
|
||||||
|
|
||||||
private static final TIntSet MOUSE_BUTTONS = new TIntHashSet();
|
private static final TIntSet MOUSE_BUTTONS = new TIntHashSet();
|
||||||
|
|
||||||
private static final String KEY_PREFIX = "GLFW_KEY_";
|
private static final String KEY_PREFIX = "GLFW_KEY_";
|
||||||
private static final String MOUSE_BUTTON_PREFIX = "GLFW_MOUSE_BUTTON_";
|
private static final String MOUSE_BUTTON_PREFIX = "GLFW_MOUSE_BUTTON_";
|
||||||
|
|
||||||
private static final Set<String> IGNORE_FIELDS =
|
private static final Set<String> IGNORE_FIELDS = new HashSet<>(
|
||||||
new HashSet<>(Arrays.asList(
|
Arrays.asList("GLFW_KEY_UNKNOWN", "GLFW_KEY_LAST", "GLFW_MOUSE_BUTTON_LAST", "GLFW_MOUSE_BUTTON_1", // Alias
|
||||||
"GLFW_KEY_UNKNOWN",
|
// for
|
||||||
"GLFW_KEY_LAST",
|
// LEFT
|
||||||
"GLFW_MOUSE_BUTTON_LAST",
|
|
||||||
"GLFW_MOUSE_BUTTON_1", // Alias for LEFT
|
|
||||||
"GLFW_MOUSE_BUTTON_2", // Alias for RIGHT
|
"GLFW_MOUSE_BUTTON_2", // Alias for RIGHT
|
||||||
"GLFW_MOUSE_BUTTON_3" // Alias for MIDDLE
|
"GLFW_MOUSE_BUTTON_3" // Alias for MIDDLE
|
||||||
));
|
));
|
||||||
|
|
||||||
static {
|
static {
|
||||||
initializeDictionary();
|
initializeDictionary();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void initializeDictionary() {
|
private static void initializeDictionary() {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
for (Field field : GLFW.class.getFields()) {
|
for (Field field : GLFW.class.getFields()) {
|
||||||
if (!Modifier.isStatic(field.getModifiers())) continue;
|
if (!Modifier.isStatic(field.getModifiers()))
|
||||||
if (!Modifier.isFinal(field.getModifiers())) continue;
|
continue;
|
||||||
|
if (!Modifier.isFinal(field.getModifiers()))
|
||||||
|
continue;
|
||||||
|
|
||||||
String name = field.getName();
|
String name = field.getName();
|
||||||
|
|
||||||
if (
|
if (!name.startsWith(KEY_PREFIX) && !name.startsWith(MOUSE_BUTTON_PREFIX))
|
||||||
!name.startsWith(KEY_PREFIX) &&
|
continue;
|
||||||
!name.startsWith(MOUSE_BUTTON_PREFIX)
|
|
||||||
) continue;
|
if (IGNORE_FIELDS.contains(name))
|
||||||
|
continue;
|
||||||
if (IGNORE_FIELDS.contains(name)) continue;
|
|
||||||
|
|
||||||
addToDictionary(field);
|
addToDictionary(field);
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (IllegalAccessException e) {
|
} catch (IllegalAccessException e) {
|
||||||
throw new RuntimeException(e);
|
CrashReports.report(e, "Cannot access GLFW constants");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void addToDictionary(Field field)
|
private static void addToDictionary(Field field) throws IllegalAccessException {
|
||||||
throws IllegalAccessException {
|
|
||||||
|
|
||||||
int value = field.getInt(null);
|
int value = field.getInt(null);
|
||||||
String name = field.getName();
|
String name = field.getName();
|
||||||
|
|
||||||
if (name.startsWith(KEY_PREFIX)) {
|
if (name.startsWith(KEY_PREFIX)) {
|
||||||
name = name.substring(KEY_PREFIX.length());
|
name = name.substring(KEY_PREFIX.length());
|
||||||
} else if (name.startsWith(MOUSE_BUTTON_PREFIX)) {
|
} else if (name.startsWith(MOUSE_BUTTON_PREFIX)) {
|
||||||
name = "MOUSE_" + name.substring(MOUSE_BUTTON_PREFIX.length());
|
name = "MOUSE_" + name.substring(MOUSE_BUTTON_PREFIX.length());
|
||||||
MOUSE_BUTTONS.add(value);
|
MOUSE_BUTTONS.add(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CODES_TO_NAMES.containsKey(value)) {
|
if (CODES_TO_NAMES.containsKey(value)) {
|
||||||
throw new RuntimeException(
|
CrashReports.report(null, "Duplicate keys: %s and %s both map to %d(0x%s)",
|
||||||
"Duplicate keys: " + CODES_TO_NAMES.get(value) +
|
CODES_TO_NAMES.get(value), name, value, Integer.toHexString(value));
|
||||||
" and " + name + " both map to " + value +
|
|
||||||
"(0x" + Integer.toHexString(value) + ")"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CODES_TO_NAMES.put(value, name);
|
CODES_TO_NAMES.put(value, name);
|
||||||
NAMES_TO_CODES.put(name, value);
|
NAMES_TO_CODES.put(name, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getInternalName(int code) {
|
public static String getInternalName(int code) {
|
||||||
String result = CODES_TO_NAMES.get(code);
|
String result = CODES_TO_NAMES.get(code);
|
||||||
|
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
return "UNKNOWN";
|
return "UNKNOWN";
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getDisplayName(int code) {
|
public static String getDisplayName(int code) {
|
||||||
String name = getInternalName(code);
|
String name = getInternalName(code);
|
||||||
|
|
||||||
if (name.startsWith("KP_")) {
|
if (name.startsWith("KP_")) {
|
||||||
name = "KEYPAD_" + name.substring("KP_".length());
|
name = "KEYPAD_" + name.substring("KP_".length());
|
||||||
}
|
}
|
||||||
|
|
||||||
name = Character.toTitleCase(name.charAt(0)) +
|
name = Character.toTitleCase(name.charAt(0)) + name.substring(1).toLowerCase();
|
||||||
name.substring(1).toLowerCase();
|
|
||||||
|
|
||||||
name = name.replace('_', ' ');
|
name = name.replace('_', ' ');
|
||||||
|
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int getCode(String internalName) {
|
public static int getCode(String internalName) {
|
||||||
if (NAMES_TO_CODES.containsKey(internalName)) {
|
if (NAMES_TO_CODES.containsKey(internalName)) {
|
||||||
return -1;
|
return -1;
|
||||||
@ -140,7 +133,7 @@ public class Keys {
|
|||||||
return NAMES_TO_CODES.get(internalName);
|
return NAMES_TO_CODES.get(internalName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isMouse(int code) {
|
public static boolean isMouse(int code) {
|
||||||
return MOUSE_BUTTONS.contains(code);
|
return MOUSE_BUTTONS.contains(code);
|
||||||
}
|
}
|
||||||
|
@ -13,72 +13,67 @@ import ru.windcorp.progressia.client.graphics.backend.RenderTaskQueue;
|
|||||||
import ru.windcorp.progressia.common.resource.Resource;
|
import ru.windcorp.progressia.common.resource.Resource;
|
||||||
import ru.windcorp.progressia.common.util.BinUtil;
|
import ru.windcorp.progressia.common.util.BinUtil;
|
||||||
import ru.windcorp.progressia.common.util.Named;
|
import ru.windcorp.progressia.common.util.Named;
|
||||||
|
import ru.windcorp.progressia.common.util.crash.CrashReports;
|
||||||
|
|
||||||
public class Atlases {
|
public class Atlases {
|
||||||
|
|
||||||
public static class AtlasGroup extends Named {
|
public static class AtlasGroup extends Named {
|
||||||
private final int atlasSize;
|
private final int atlasSize;
|
||||||
|
|
||||||
public AtlasGroup(String name, int atlasSize) {
|
public AtlasGroup(String name, int atlasSize) {
|
||||||
super(name);
|
super(name);
|
||||||
this.atlasSize = atlasSize;
|
this.atlasSize = atlasSize;
|
||||||
|
|
||||||
if (!BinUtil.isPowerOf2(atlasSize)) {
|
if (!BinUtil.isPowerOf2(atlasSize)) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException("Atlas size " + atlasSize + " is not a power of 2");
|
||||||
"Atlas size " + atlasSize
|
|
||||||
+ " is not a power of 2"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getAtlasSize() {
|
public int getAtlasSize() {
|
||||||
return atlasSize;
|
return atlasSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return super.hashCode();
|
return super.hashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
return super.equals(obj);
|
return super.equals(obj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Atlas {
|
public static class Atlas {
|
||||||
private final AtlasGroup group;
|
private final AtlasGroup group;
|
||||||
|
|
||||||
private final TextureDataEditor editor;
|
private final TextureDataEditor editor;
|
||||||
private int nextX, nextY;
|
private int nextX, nextY;
|
||||||
private int rowHeight;
|
private int rowHeight;
|
||||||
|
|
||||||
private final TexturePrimitive primitive;
|
private final TexturePrimitive primitive;
|
||||||
|
|
||||||
public Atlas(AtlasGroup group) {
|
public Atlas(AtlasGroup group) {
|
||||||
this.group = group;
|
this.group = group;
|
||||||
int size = group.getAtlasSize();
|
int size = group.getAtlasSize();
|
||||||
|
|
||||||
this.editor = new TextureDataEditor(size, size, size, size, SETTINGS);
|
this.editor = new TextureDataEditor(size, size, size, size, SETTINGS);
|
||||||
this.primitive = new TexturePrimitive(editor.getData());
|
this.primitive = new TexturePrimitive(editor.getData());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Sprite addSprite(TextureData data) {
|
public Sprite addSprite(TextureData data) {
|
||||||
int width = data.getContentWidth();
|
int width = data.getContentWidth();
|
||||||
int height = data.getContentHeight();
|
int height = data.getContentHeight();
|
||||||
|
|
||||||
selectPosition(width, height);
|
selectPosition(width, height);
|
||||||
|
|
||||||
editor.draw(data, nextX, nextY);
|
editor.draw(data, nextX, nextY);
|
||||||
|
|
||||||
Sprite result = new Sprite(
|
Sprite result = new Sprite(getPrimitive(), toPrimitiveCoords(nextX, nextY),
|
||||||
getPrimitive(),
|
toPrimitiveCoords(width, height));
|
||||||
toPrimitiveCoords(nextX, nextY),
|
|
||||||
toPrimitiveCoords(width, height)
|
|
||||||
);
|
|
||||||
|
|
||||||
nextX += width;
|
nextX += width;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,10 +82,10 @@ public class Atlases {
|
|||||||
// Wrapping
|
// Wrapping
|
||||||
nextY += rowHeight; // Move to next row
|
nextY += rowHeight; // Move to next row
|
||||||
rowHeight = height; // Next row is at least 'height' high
|
rowHeight = height; // Next row is at least 'height' high
|
||||||
nextX = 0; // Start the row over
|
nextX = 0; // Start the row over
|
||||||
} else {
|
} else {
|
||||||
// Not wrapping
|
// Not wrapping
|
||||||
|
|
||||||
// Update rowHeight if necessary
|
// Update rowHeight if necessary
|
||||||
if (rowHeight < height) {
|
if (rowHeight < height) {
|
||||||
rowHeight = height;
|
rowHeight = height;
|
||||||
@ -99,10 +94,7 @@ public class Atlases {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Vec2 toPrimitiveCoords(int x, int y) {
|
private Vec2 toPrimitiveCoords(int x, int y) {
|
||||||
return new Vec2(
|
return new Vec2(toPrimitiveCoord(x), toPrimitiveCoord(y));
|
||||||
toPrimitiveCoord(x),
|
|
||||||
toPrimitiveCoord(y)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private float toPrimitiveCoord(int c) {
|
private float toPrimitiveCoord(int c) {
|
||||||
@ -112,87 +104,82 @@ public class Atlases {
|
|||||||
public boolean canAddSprite(TextureData data) {
|
public boolean canAddSprite(TextureData data) {
|
||||||
int width = data.getContentWidth();
|
int width = data.getContentWidth();
|
||||||
int height = data.getContentHeight();
|
int height = data.getContentHeight();
|
||||||
|
|
||||||
// Try to fit without wrapping
|
// Try to fit without wrapping
|
||||||
|
|
||||||
if (nextY + height > getSize())
|
if (nextY + height > getSize())
|
||||||
// Does not fit vertically
|
// Does not fit vertically
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (nextX + width <= getSize())
|
if (nextX + width <= getSize())
|
||||||
// Can place at (nextX; nextY)
|
// Can place at (nextX; nextY)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// Try wrapping
|
// Try wrapping
|
||||||
|
|
||||||
if (width > getSize())
|
if (width > getSize())
|
||||||
// GTFO. We couldn't fit if if we tried
|
// GTFO. We couldn't fit if if we tried
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (nextY + rowHeight + height > getSize())
|
if (nextY + rowHeight + height > getSize())
|
||||||
// Does not fit vertically when wrapped
|
// Does not fit vertically when wrapped
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Can place at (0; nextY + rowHeight)
|
// Can place at (0; nextY + rowHeight)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AtlasGroup getGroup() {
|
public AtlasGroup getGroup() {
|
||||||
return group;
|
return group;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TexturePrimitive getPrimitive() {
|
public TexturePrimitive getPrimitive() {
|
||||||
return primitive;
|
return primitive;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getSize() {
|
public int getSize() {
|
||||||
return editor.getBufferWidth();
|
return editor.getBufferWidth();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final TextureSettings SETTINGS = new TextureSettings(false);
|
private static final TextureSettings SETTINGS = new TextureSettings(false);
|
||||||
|
|
||||||
private static final Map<Resource, Sprite> LOADED =
|
private static final Map<Resource, Sprite> LOADED = new HashMap<>();
|
||||||
new HashMap<>();
|
private static final Multimap<AtlasGroup, Atlas> ATLASES = MultimapBuilder.hashKeys().arrayListValues().build();
|
||||||
private static final Multimap<AtlasGroup, Atlas> ATLASES =
|
|
||||||
MultimapBuilder.hashKeys().arrayListValues().build();
|
|
||||||
|
|
||||||
public static Sprite getSprite(Resource resource, AtlasGroup group) {
|
public static Sprite getSprite(Resource resource, AtlasGroup group) {
|
||||||
return LOADED.computeIfAbsent(resource, k -> loadSprite(k, group));
|
return LOADED.computeIfAbsent(resource, k -> loadSprite(k, group));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Sprite loadSprite(Resource resource, AtlasGroup group) {
|
private static Sprite loadSprite(Resource resource, AtlasGroup group) {
|
||||||
try {
|
try {
|
||||||
TextureDataEditor data =
|
TextureDataEditor data = TextureLoader.loadPixels(resource, SETTINGS);
|
||||||
TextureLoader.loadPixels(resource, SETTINGS);
|
|
||||||
|
|
||||||
return loadSprite(data.getData(), group);
|
return loadSprite(data.getData(), group);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException(e);
|
CrashReports.report(e, "Problem with load atlases sprite");
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Sprite loadSprite(TextureData data, AtlasGroup group) {
|
public static Sprite loadSprite(TextureData data, AtlasGroup group) {
|
||||||
Atlas atlas = getReadyAtlas(group, data);
|
Atlas atlas = getReadyAtlas(group, data);
|
||||||
return atlas.addSprite(data);
|
return atlas.addSprite(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Atlas getReadyAtlas(AtlasGroup group, TextureData data) {
|
private static Atlas getReadyAtlas(AtlasGroup group, TextureData data) {
|
||||||
List<Atlas> atlases = (List<Atlas>) ATLASES.get(group);
|
List<Atlas> atlases = (List<Atlas>) ATLASES.get(group);
|
||||||
|
|
||||||
if (
|
if (atlases.isEmpty() || !(atlases.get(atlases.size() - 1).canAddSprite(data))) {
|
||||||
atlases.isEmpty() ||
|
|
||||||
!(atlases.get(atlases.size() - 1).canAddSprite(data))
|
|
||||||
) {
|
|
||||||
Atlas newAtlas = new Atlas(group);
|
Atlas newAtlas = new Atlas(group);
|
||||||
|
|
||||||
if (!newAtlas.canAddSprite(data)) {
|
if (!newAtlas.canAddSprite(data)) {
|
||||||
throw new RuntimeException("Could not fit tex into atlas of size " + newAtlas.getSize());
|
CrashReports.report(null, "Could not fit tex into atlas of size %d", newAtlas.getSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
atlases.add(newAtlas);
|
atlases.add(newAtlas);
|
||||||
}
|
}
|
||||||
|
|
||||||
return atlases.get(atlases.size() - 1);
|
return atlases.get(atlases.size() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -201,7 +188,8 @@ public class Atlases {
|
|||||||
RenderTaskQueue.invokeLater(atlas.getPrimitive()::load);
|
RenderTaskQueue.invokeLater(atlas.getPrimitive()::load);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private Atlases() {}
|
private Atlases() {
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -6,21 +6,22 @@ import java.util.Map;
|
|||||||
|
|
||||||
import ru.windcorp.progressia.common.resource.Resource;
|
import ru.windcorp.progressia.common.resource.Resource;
|
||||||
import ru.windcorp.progressia.common.resource.ResourceManager;
|
import ru.windcorp.progressia.common.resource.ResourceManager;
|
||||||
|
import ru.windcorp.progressia.common.util.crash.CrashReports;
|
||||||
|
|
||||||
public class SimpleTextures {
|
public class SimpleTextures {
|
||||||
|
|
||||||
private static final TextureSettings SETTINGS = new TextureSettings(false);
|
private static final TextureSettings SETTINGS = new TextureSettings(false);
|
||||||
|
|
||||||
private static final Map<Resource, Texture> TEXTURES = new HashMap<>();
|
private static final Map<Resource, Texture> TEXTURES = new HashMap<>();
|
||||||
|
|
||||||
public static Texture get(Resource resource) {
|
public static Texture get(Resource resource) {
|
||||||
return TEXTURES.computeIfAbsent(resource, SimpleTextures::load);
|
return TEXTURES.computeIfAbsent(resource, SimpleTextures::load);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Texture get(String textureName) {
|
public static Texture get(String textureName) {
|
||||||
return get(ResourceManager.getTextureResource(textureName));
|
return get(ResourceManager.getTextureResource(textureName));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Texture load(Resource resource) {
|
private static Texture load(Resource resource) {
|
||||||
try {
|
try {
|
||||||
TextureDataEditor data =
|
TextureDataEditor data =
|
||||||
@ -30,9 +31,10 @@ public class SimpleTextures {
|
|||||||
new Sprite(new TexturePrimitive(data.getData()))
|
new Sprite(new TexturePrimitive(data.getData()))
|
||||||
);
|
);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException(e);
|
CrashReports.report(e, "Problem with load texture");
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private SimpleTextures() {}
|
private SimpleTextures() {}
|
||||||
|
@ -24,27 +24,28 @@ import java.util.Arrays;
|
|||||||
|
|
||||||
import ru.windcorp.progressia.client.graphics.backend.OpenGLObjectTracker;
|
import ru.windcorp.progressia.client.graphics.backend.OpenGLObjectTracker;
|
||||||
import ru.windcorp.progressia.client.graphics.backend.OpenGLObjectTracker.OpenGLDeletable;
|
import ru.windcorp.progressia.client.graphics.backend.OpenGLObjectTracker.OpenGLDeletable;
|
||||||
|
import ru.windcorp.progressia.common.util.crash.CrashReports;
|
||||||
|
|
||||||
public class TexturePrimitive implements OpenGLDeletable {
|
public class TexturePrimitive implements OpenGLDeletable {
|
||||||
|
|
||||||
private static final int NOT_LOADED = -1;
|
private static final int NOT_LOADED = -1;
|
||||||
|
|
||||||
private static int[] currentlyBound = new int[32];
|
private static int[] currentlyBound = new int[32];
|
||||||
static {
|
static {
|
||||||
Arrays.fill(currentlyBound, NOT_LOADED);
|
Arrays.fill(currentlyBound, NOT_LOADED);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int handle = NOT_LOADED;
|
private int handle = NOT_LOADED;
|
||||||
private TextureData pixels;
|
private TextureData pixels;
|
||||||
|
|
||||||
public TexturePrimitive(TextureData pixels) {
|
public TexturePrimitive(TextureData pixels) {
|
||||||
this.pixels = pixels;
|
this.pixels = pixels;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TextureData getData() {
|
public TextureData getData() {
|
||||||
return pixels;
|
return pixels;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getBufferWidth() {
|
public int getBufferWidth() {
|
||||||
return pixels.getBufferWidth();
|
return pixels.getBufferWidth();
|
||||||
}
|
}
|
||||||
@ -64,21 +65,21 @@ public class TexturePrimitive implements OpenGLDeletable {
|
|||||||
public boolean isLoaded() {
|
public boolean isLoaded() {
|
||||||
return handle != NOT_LOADED;
|
return handle != NOT_LOADED;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void bind(int slot) {
|
public void bind(int slot) {
|
||||||
if (!isLoaded()) {
|
if (!isLoaded()) {
|
||||||
load();
|
load();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentlyBound[slot] == handle) {
|
if (currentlyBound[slot] == handle) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int code = GL_TEXTURE0 + slot;
|
int code = GL_TEXTURE0 + slot;
|
||||||
|
|
||||||
glActiveTexture(code);
|
glActiveTexture(code);
|
||||||
glBindTexture(GL_TEXTURE_2D, handle);
|
glBindTexture(GL_TEXTURE_2D, handle);
|
||||||
|
|
||||||
currentlyBound[slot] = handle;
|
currentlyBound[slot] = handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,9 +88,9 @@ public class TexturePrimitive implements OpenGLDeletable {
|
|||||||
|
|
||||||
handle = pixels.load();
|
handle = pixels.load();
|
||||||
OpenGLObjectTracker.register(this);
|
OpenGLObjectTracker.register(this);
|
||||||
|
|
||||||
if (handle < 0) {
|
if (handle < 0) {
|
||||||
throw new RuntimeException("oops");
|
CrashReports.report(null, "Failed to create texture");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,8 @@ package ru.windcorp.progressia.client.localization;
|
|||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
import ru.windcorp.progressia.common.util.crash.CrashReports;
|
||||||
|
|
||||||
public class Localizer {
|
public class Localizer {
|
||||||
private static final Localizer INSTANCE = new Localizer("assets/languages/", "en-US");
|
private static final Localizer INSTANCE = new Localizer("assets/languages/", "en-US");
|
||||||
|
|
||||||
@ -17,7 +19,7 @@ public class Localizer {
|
|||||||
private final Collection<WeakReference<LocaleListener>> listeners =
|
private final Collection<WeakReference<LocaleListener>> listeners =
|
||||||
Collections.synchronizedCollection(new LinkedList<>());
|
Collections.synchronizedCollection(new LinkedList<>());
|
||||||
|
|
||||||
//lang list must be in the same folder as .lang files
|
// lang list must be in the same folder as .lang files
|
||||||
public Localizer(String langFolder) {
|
public Localizer(String langFolder) {
|
||||||
this.langFolder = langFolder;
|
this.langFolder = langFolder;
|
||||||
this.langList = new Parser(langFolder + "lang_list.txt").parse();
|
this.langList = new Parser(langFolder + "lang_list.txt").parse();
|
||||||
@ -41,7 +43,7 @@ public class Localizer {
|
|||||||
data = new Parser(langFolder + this.language + ".lang").parse();
|
data = new Parser(langFolder + this.language + ".lang").parse();
|
||||||
pokeListeners(language);
|
pokeListeners(language);
|
||||||
} else {
|
} else {
|
||||||
throw new RuntimeException("Language not found: " + language);
|
CrashReports.report(null, "Language not found: %s", language);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,7 +66,7 @@ public class Localizer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void pokeListeners(String newLanguage) {
|
private void pokeListeners(String newLanguage) {
|
||||||
//TODO extract as weak bus listener class
|
// TODO extract as weak bus listener class
|
||||||
synchronized (listeners) {
|
synchronized (listeners) {
|
||||||
Iterator<WeakReference<LocaleListener>> iterator = listeners.iterator();
|
Iterator<WeakReference<LocaleListener>> iterator = listeners.iterator();
|
||||||
while (iterator.hasNext()) {
|
while (iterator.hasNext()) {
|
||||||
|
@ -3,6 +3,7 @@ package ru.windcorp.progressia.client.localization;
|
|||||||
import ru.windcorp.jputil.chars.EscapeException;
|
import ru.windcorp.jputil.chars.EscapeException;
|
||||||
import ru.windcorp.jputil.chars.Escaper;
|
import ru.windcorp.jputil.chars.Escaper;
|
||||||
import ru.windcorp.progressia.common.resource.ResourceManager;
|
import ru.windcorp.progressia.common.resource.ResourceManager;
|
||||||
|
import ru.windcorp.progressia.common.util.crash.CrashReports;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
@ -54,7 +55,7 @@ public class Parser {
|
|||||||
if (c == '=') {
|
if (c == '=') {
|
||||||
String key = ESCAPER.escape(stringBuilder.toString());
|
String key = ESCAPER.escape(stringBuilder.toString());
|
||||||
stringBuilder.setLength(0);
|
stringBuilder.setLength(0);
|
||||||
rawData.read(); //skip a char
|
rawData.read(); // skip a char
|
||||||
while (true) {
|
while (true) {
|
||||||
code = rawData.read();
|
code = rawData.read();
|
||||||
if (code == -1) {
|
if (code == -1) {
|
||||||
@ -80,7 +81,8 @@ public class Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
} catch (IOException | EscapeException e) {
|
} catch (IOException | EscapeException e) {
|
||||||
throw new RuntimeException(e);
|
CrashReports.report(e, "Problems with parsing");
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
return parsedData;
|
return parsedData;
|
||||||
}
|
}
|
||||||
|
@ -7,16 +7,17 @@ import ru.windcorp.progressia.client.graphics.texture.TexturePrimitive;
|
|||||||
import ru.windcorp.progressia.client.graphics.texture.TextureSettings;
|
import ru.windcorp.progressia.client.graphics.texture.TextureSettings;
|
||||||
import ru.windcorp.progressia.common.resource.ResourceManager;
|
import ru.windcorp.progressia.common.resource.ResourceManager;
|
||||||
import ru.windcorp.progressia.common.util.NamespacedRegistry;
|
import ru.windcorp.progressia.common.util.NamespacedRegistry;
|
||||||
|
import ru.windcorp.progressia.common.util.crash.CrashReports;
|
||||||
|
|
||||||
public class EntityRenderRegistry extends NamespacedRegistry<EntityRender> {
|
public class EntityRenderRegistry extends NamespacedRegistry<EntityRender> {
|
||||||
|
|
||||||
private static final EntityRenderRegistry INSTANCE =
|
private static final EntityRenderRegistry INSTANCE =
|
||||||
new EntityRenderRegistry();
|
new EntityRenderRegistry();
|
||||||
|
|
||||||
public static EntityRenderRegistry getInstance() {
|
public static EntityRenderRegistry getInstance() {
|
||||||
return INSTANCE;
|
return INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TexturePrimitive getEntityTexture(String name) {
|
public static TexturePrimitive getEntityTexture(String name) {
|
||||||
try {
|
try {
|
||||||
return new TexturePrimitive(
|
return new TexturePrimitive(
|
||||||
@ -28,7 +29,8 @@ public class EntityRenderRegistry extends NamespacedRegistry<EntityRender> {
|
|||||||
).getData()
|
).getData()
|
||||||
);
|
);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException(e);
|
CrashReports.report(e, "__DOC__ME__");
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,50 +30,53 @@ import com.google.common.io.CharStreams;
|
|||||||
|
|
||||||
import ru.windcorp.progressia.Progressia;
|
import ru.windcorp.progressia.Progressia;
|
||||||
import ru.windcorp.progressia.common.util.Named;
|
import ru.windcorp.progressia.common.util.Named;
|
||||||
|
import ru.windcorp.progressia.common.util.crash.CrashReports;
|
||||||
|
|
||||||
public class Resource extends Named {
|
public class Resource extends Named {
|
||||||
|
|
||||||
public Resource(String name) {
|
public Resource(String name) {
|
||||||
super(name);
|
super(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public InputStream getInputStream() {
|
public InputStream getInputStream() {
|
||||||
// TODO Do proper resource lookup
|
// TODO Do proper resource lookup
|
||||||
return Progressia.class.getClassLoader().getResourceAsStream(getName());
|
return Progressia.class.getClassLoader().getResourceAsStream(getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Reader getReader() {
|
public Reader getReader() {
|
||||||
return new InputStreamReader(getInputStream());
|
return new InputStreamReader(getInputStream());
|
||||||
}
|
}
|
||||||
|
|
||||||
public String readAsString() {
|
public String readAsString() {
|
||||||
try (Reader reader = getReader()) {
|
try (Reader reader = getReader()) {
|
||||||
return CharStreams.toString(reader);
|
return CharStreams.toString(reader);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException(e); // TODO handle gracefully
|
CrashReports.report(e, "__DOC__ME__");
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ByteBuffer readAsBytes(ByteBuffer output) {
|
public ByteBuffer readAsBytes(ByteBuffer output) {
|
||||||
byte[] byteArray;
|
byte[] byteArray;
|
||||||
try (InputStream stream = getInputStream()) {
|
try (InputStream stream = getInputStream()) {
|
||||||
byteArray = ByteStreams.toByteArray(stream);
|
byteArray = ByteStreams.toByteArray(stream);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException(e); // TODO handle gracefully
|
CrashReports.report(e, "__DOC__ME__");
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (output == null || output.remaining() < byteArray.length) {
|
if (output == null || output.remaining() < byteArray.length) {
|
||||||
output = BufferUtils.createByteBuffer(byteArray.length);
|
output = BufferUtils.createByteBuffer(byteArray.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
int position = output.position();
|
int position = output.position();
|
||||||
output.put(byteArray);
|
output.put(byteArray);
|
||||||
output.limit(output.position());
|
output.limit(output.position());
|
||||||
output.position(position);
|
output.position(position);
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ByteBuffer readAsBytes() {
|
public ByteBuffer readAsBytes() {
|
||||||
return readAsBytes(null);
|
return readAsBytes(null);
|
||||||
}
|
}
|
||||||
|
@ -1,216 +1,212 @@
|
|||||||
package ru.windcorp.progressia.common.util.crash;
|
package ru.windcorp.progressia.common.util.crash;
|
||||||
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.apache.logging.log4j.core.util.StringBuilderWriter;
|
import org.apache.logging.log4j.core.util.StringBuilderWriter;
|
||||||
|
|
||||||
import java.io.BufferedWriter;
|
import ru.windcorp.jputil.chars.StringUtil;
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.PrintWriter;
|
import java.io.BufferedWriter;
|
||||||
import java.io.Writer;
|
import java.io.IOException;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.io.PrintWriter;
|
||||||
import java.nio.file.Files;
|
import java.io.Writer;
|
||||||
import java.nio.file.Path;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Files;
|
||||||
import java.text.DateFormat;
|
import java.nio.file.Path;
|
||||||
import java.text.SimpleDateFormat;
|
import java.nio.file.Paths;
|
||||||
import java.util.*;
|
import java.text.DateFormat;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
public class CrashReportGenerator {
|
import java.util.*;
|
||||||
|
|
||||||
private CrashReportGenerator() {}
|
public class CrashReports {
|
||||||
|
|
||||||
private static final Path CRASH_REPORTS_PATH = Paths.get("crash-reports");
|
private CrashReports() {
|
||||||
|
}
|
||||||
private static final Collection<ContextProvider> PROVIDERS =
|
|
||||||
Collections.synchronizedCollection(new ArrayList<>());
|
private static final Path CRASH_REPORTS_PATH = Paths.get("crash-reports");
|
||||||
|
|
||||||
private static final Collection<Analyzer> ANALYZERS =
|
private static final Collection<ContextProvider> PROVIDERS = Collections.synchronizedCollection(new ArrayList<>());
|
||||||
Collections.synchronizedCollection(new ArrayList<>());
|
|
||||||
|
private static final Collection<Analyzer> ANALYZERS = Collections.synchronizedCollection(new ArrayList<>());
|
||||||
private static final Logger LOGGER = LogManager.getLogger("crash");
|
|
||||||
|
private static final Logger LOGGER = LogManager.getLogger("crash");
|
||||||
/**
|
|
||||||
* <em>This method never returns.</em>
|
/**
|
||||||
* <p>
|
* <em>This method never returns.</em>
|
||||||
* TODO document
|
* <p>
|
||||||
* @param throwable
|
* TODO document
|
||||||
* @param messageFormat
|
*
|
||||||
* @param args
|
* @param throwable
|
||||||
*/
|
* @param messageFormat
|
||||||
public static void crash(Throwable throwable, String messageFormat, Object... args) {
|
* @param args
|
||||||
StringBuilder output = new StringBuilder();
|
*/
|
||||||
|
public static void report(Throwable throwable, String messageFormat, Object... args) {
|
||||||
appendContextProviders(output);
|
StringBuilder output = new StringBuilder();
|
||||||
addSeparator(output);
|
|
||||||
if (appendAnalyzers(output, throwable, messageFormat, args)) {
|
appendContextProviders(output);
|
||||||
addSeparator(output);
|
addSeparator(output);
|
||||||
}
|
if (appendAnalyzers(output, throwable, messageFormat, args)) {
|
||||||
|
addSeparator(output);
|
||||||
appendMessageFormat(output, messageFormat, args);
|
}
|
||||||
|
|
||||||
appendStackTrace(output, throwable);
|
appendMessageFormat(output, messageFormat, args);
|
||||||
|
|
||||||
export(output.toString());
|
appendStackTrace(output, throwable);
|
||||||
|
|
||||||
System.exit(0);
|
export(output.toString());
|
||||||
}
|
|
||||||
|
System.exit(0);
|
||||||
private static void appendContextProviders(StringBuilder output) {
|
}
|
||||||
|
|
||||||
// Do a local copy to avoid deadlocks -OLEGSHA
|
private static void appendContextProviders(StringBuilder output) {
|
||||||
ContextProvider[] localProvidersCopy =
|
|
||||||
PROVIDERS.toArray(new ContextProvider[PROVIDERS.size()]);
|
// Do a local copy to avoid deadlocks -OLEGSHA
|
||||||
|
ContextProvider[] localProvidersCopy = PROVIDERS.toArray(new ContextProvider[PROVIDERS.size()]);
|
||||||
for (ContextProvider provider : localProvidersCopy) {
|
|
||||||
if (provider == null) continue;
|
for (ContextProvider provider : localProvidersCopy) {
|
||||||
|
if (provider == null)
|
||||||
addSeparator(output);
|
continue;
|
||||||
|
|
||||||
try {
|
addSeparator(output);
|
||||||
Map<String, String> buf = new HashMap<>();
|
|
||||||
provider.provideContext(buf);
|
try {
|
||||||
|
Map<String, String> buf = new HashMap<>();
|
||||||
if (!buf.isEmpty()) {
|
provider.provideContext(buf);
|
||||||
output.append("Provider name: ").append(provider.getName()).append("\n");
|
|
||||||
for (Map.Entry<String, String> entry : buf.entrySet()) {
|
if (!buf.isEmpty()) {
|
||||||
output.append(entry.getKey()).append(": ").append(entry.getValue()).append("\n");
|
output.append("Provider name: ").append(provider.getName()).append("\n");
|
||||||
}
|
for (Map.Entry<String, String> entry : buf.entrySet()) {
|
||||||
}
|
output.append(entry.getKey()).append(": ").append(entry.getValue()).append("\n");
|
||||||
} catch (Throwable t) {
|
}
|
||||||
output.append("\n");
|
}
|
||||||
|
} catch (Throwable t) {
|
||||||
String providerName;
|
output.append("\n");
|
||||||
|
|
||||||
try {
|
String providerName;
|
||||||
providerName = provider.getName();
|
|
||||||
} catch (Throwable t1) {
|
try {
|
||||||
providerName = provider.getClass().getName();
|
providerName = provider.getName();
|
||||||
}
|
} catch (Throwable t1) {
|
||||||
|
providerName = provider.getClass().getName();
|
||||||
output.append(providerName).append(" is broken").append("\n");
|
}
|
||||||
// ContextProvider is broken
|
|
||||||
}
|
output.append(providerName).append(" is broken").append("\n");
|
||||||
}
|
// ContextProvider is broken
|
||||||
}
|
}
|
||||||
|
}
|
||||||
private static boolean appendAnalyzers(
|
}
|
||||||
StringBuilder output,
|
|
||||||
Throwable throwable, String messageFormat, Object[] args
|
private static boolean appendAnalyzers(StringBuilder output, Throwable throwable, String messageFormat,
|
||||||
) {
|
Object[] args) {
|
||||||
boolean analyzerResponsesExist = false;
|
boolean analyzerResponsesExist = false;
|
||||||
|
|
||||||
// Do a local copy to avoid deadlocks -OLEGSHA
|
// Do a local copy to avoid deadlocks -OLEGSHA
|
||||||
Analyzer[] localAnalyzersCopy =
|
Analyzer[] localAnalyzersCopy = ANALYZERS.toArray(new Analyzer[ANALYZERS.size()]);
|
||||||
ANALYZERS.toArray(new Analyzer[ANALYZERS.size()]);
|
|
||||||
|
for (Analyzer analyzer : localAnalyzersCopy) {
|
||||||
for (Analyzer analyzer : localAnalyzersCopy) {
|
if (analyzer == null)
|
||||||
if (analyzer == null) continue;
|
continue;
|
||||||
|
|
||||||
String answer;
|
String answer;
|
||||||
try {
|
try {
|
||||||
answer = analyzer.analyze(throwable, messageFormat, args);
|
answer = analyzer.analyze(throwable, messageFormat, args);
|
||||||
|
|
||||||
if (answer != null && !answer.isEmpty()) {
|
if (answer != null && !answer.isEmpty()) {
|
||||||
analyzerResponsesExist = true;
|
analyzerResponsesExist = true;
|
||||||
output.append(analyzer.getName()).append(": ").append(answer).append("\n");
|
output.append(analyzer.getName()).append(": ").append(answer).append("\n");
|
||||||
}
|
}
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
analyzerResponsesExist = true;
|
analyzerResponsesExist = true;
|
||||||
|
|
||||||
output.append("\n");
|
output.append("\n");
|
||||||
|
|
||||||
String analyzerName;
|
String analyzerName;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
analyzerName = analyzer.getName();
|
analyzerName = analyzer.getName();
|
||||||
} catch (Throwable t1) {
|
} catch (Throwable t1) {
|
||||||
analyzerName = analyzer.getClass().getName();
|
analyzerName = analyzer.getClass().getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
output.append(analyzerName).append(" is broken").append("\n");
|
output.append(analyzerName).append(" is broken").append("\n");
|
||||||
// Analyzer is broken
|
// Analyzer is broken
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return analyzerResponsesExist;
|
return analyzerResponsesExist;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void appendMessageFormat(StringBuilder output, String messageFormat, Object... arg) {
|
private static void appendMessageFormat(StringBuilder output, String messageFormat, Object... arg) {
|
||||||
output.append("Provided description: \n").append(String.format(messageFormat, arg)).append("\n");
|
output.append("Provided description: \n").append(String.format(messageFormat, arg)).append("\n");
|
||||||
|
|
||||||
addSeparator(output);
|
addSeparator(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void appendStackTrace(StringBuilder output, Throwable throwable) {
|
private static void appendStackTrace(StringBuilder output, Throwable throwable) {
|
||||||
output.append("Stacktrace: \n");
|
output.append("Stacktrace: \n");
|
||||||
|
|
||||||
if (throwable == null) {
|
if (throwable == null) {
|
||||||
output.append("no Throwable provided").append("\n");
|
output.append("no Throwable provided").append("\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Formatting to a human-readable string
|
// Formatting to a human-readable string
|
||||||
Writer sink = new StringBuilderWriter(output);
|
Writer sink = new StringBuilderWriter(output);
|
||||||
try {
|
try {
|
||||||
throwable.printStackTrace(new PrintWriter(sink));
|
throwable.printStackTrace(new PrintWriter(sink));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
// PLAK
|
// PLAK
|
||||||
}
|
}
|
||||||
output.append("\n");
|
output.append("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void export(String report) {
|
private static void export(String report) {
|
||||||
try {
|
try {
|
||||||
LOGGER.fatal("/n" + report);
|
LOGGER.fatal("/n" + report);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
// PLAK
|
// PLAK
|
||||||
}
|
}
|
||||||
|
|
||||||
System.err.println(report);
|
System.err.println(report);
|
||||||
|
|
||||||
generateCrashReportFiles(report);
|
generateCrashReportFiles(report);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void generateCrashReportFiles(String output) {
|
private static void generateCrashReportFiles(String output) {
|
||||||
Date date = new Date();
|
Date date = new Date();
|
||||||
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd-HH.mm.ss");
|
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd-HH.mm.ss");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (!Files.exists(CRASH_REPORTS_PATH)) Files.createDirectory(CRASH_REPORTS_PATH);
|
if (!Files.exists(CRASH_REPORTS_PATH))
|
||||||
|
Files.createDirectory(CRASH_REPORTS_PATH);
|
||||||
createFileForCrashReport(output, CRASH_REPORTS_PATH.toString() + "/latest.log");
|
|
||||||
createFileForCrashReport(output, CRASH_REPORTS_PATH.toString() + "/crash-" + dateFormat.format(date) + ".log");
|
createFileForCrashReport(output, CRASH_REPORTS_PATH.toString() + "/latest.log");
|
||||||
} catch (Throwable t) {
|
createFileForCrashReport(output,
|
||||||
// Crash Report not created
|
CRASH_REPORTS_PATH.toString() + "/crash-" + dateFormat.format(date) + ".log");
|
||||||
}
|
} catch (Throwable t) {
|
||||||
}
|
// Crash Report not created
|
||||||
|
}
|
||||||
private static void createFileForCrashReport(String buffer, String filename) {
|
}
|
||||||
try (
|
|
||||||
BufferedWriter writer = Files.newBufferedWriter(
|
private static void createFileForCrashReport(String buffer, String filename) {
|
||||||
Paths.get(filename),
|
try (BufferedWriter writer = Files.newBufferedWriter(Paths.get(filename), StandardCharsets.UTF_8)) {
|
||||||
StandardCharsets.UTF_8
|
writer.write(buffer);
|
||||||
)
|
} catch (IOException ex) {
|
||||||
) {
|
// Crash Report not created
|
||||||
writer.write(buffer);
|
}
|
||||||
} catch (IOException ex) {
|
}
|
||||||
// Crash Report not created
|
|
||||||
}
|
public static void registerProvider(ContextProvider provider) {
|
||||||
}
|
PROVIDERS.add(provider);
|
||||||
|
}
|
||||||
public static void registerProvider(ContextProvider provider) {
|
|
||||||
PROVIDERS.add(provider);
|
public static void registerAnalyzer(Analyzer analyzer) {
|
||||||
}
|
ANALYZERS.add(analyzer);
|
||||||
|
}
|
||||||
public static void registerAnalyzer(Analyzer analyzer) {
|
|
||||||
ANALYZERS.add(analyzer);
|
private static void addSeparator(StringBuilder sb) {
|
||||||
}
|
sb.append(
|
||||||
|
// 80 chars
|
||||||
private static void addSeparator(StringBuilder sb) {
|
"--------------------------------------------------------------------------------").append("\n");
|
||||||
sb.append(
|
}
|
||||||
// 80 chars
|
}
|
||||||
"--------------------------------------------------------------------------------"
|
|
||||||
).append("\n");
|
|
||||||
}
|
|
||||||
}
|
|
@ -7,25 +7,26 @@ import java.io.IOException;
|
|||||||
import ru.windcorp.progressia.common.comms.packets.PacketWorldChange;
|
import ru.windcorp.progressia.common.comms.packets.PacketWorldChange;
|
||||||
import ru.windcorp.progressia.common.state.IOContext;
|
import ru.windcorp.progressia.common.state.IOContext;
|
||||||
import ru.windcorp.progressia.common.util.DataBuffer;
|
import ru.windcorp.progressia.common.util.DataBuffer;
|
||||||
|
import ru.windcorp.progressia.common.util.crash.CrashReports;
|
||||||
import ru.windcorp.progressia.common.world.WorldData;
|
import ru.windcorp.progressia.common.world.WorldData;
|
||||||
|
|
||||||
public class PacketEntityChange extends PacketWorldChange {
|
public class PacketEntityChange extends PacketWorldChange {
|
||||||
|
|
||||||
private long entityId;
|
private long entityId;
|
||||||
private final DataBuffer buffer = new DataBuffer();
|
private final DataBuffer buffer = new DataBuffer();
|
||||||
|
|
||||||
public PacketEntityChange() {
|
public PacketEntityChange() {
|
||||||
super("Core", "EntityChange");
|
super("Core", "EntityChange");
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getEntityId() {
|
public long getEntityId() {
|
||||||
return entityId;
|
return entityId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setEntityId(long entityId) {
|
public void setEntityId(long entityId) {
|
||||||
this.entityId = entityId;
|
this.entityId = entityId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DataBuffer getBuffer() {
|
public DataBuffer getBuffer() {
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
@ -41,19 +42,15 @@ public class PacketEntityChange extends PacketWorldChange {
|
|||||||
@Override
|
@Override
|
||||||
public void apply(WorldData world) {
|
public void apply(WorldData world) {
|
||||||
EntityData entity = world.getEntity(getEntityId());
|
EntityData entity = world.getEntity(getEntityId());
|
||||||
|
|
||||||
if (entity == null) {
|
if (entity == null) {
|
||||||
throw new RuntimeException(
|
CrashReports.report(null, "Entity with ID %d not found", getEntityId());
|
||||||
"Entity with ID " + getEntityId() + " not found"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
entity.read(getReader(), IOContext.COMMS);
|
entity.read(getReader(), IOContext.COMMS);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException(
|
CrashReports.report(e, "Entity could not be read");
|
||||||
"Entity could not be read", e
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@ import ru.windcorp.progressia.common.comms.packets.PacketWorldChange;
|
|||||||
import ru.windcorp.progressia.common.state.IOContext;
|
import ru.windcorp.progressia.common.state.IOContext;
|
||||||
import ru.windcorp.progressia.common.util.LowOverheadCache;
|
import ru.windcorp.progressia.common.util.LowOverheadCache;
|
||||||
import ru.windcorp.progressia.common.util.Vectors;
|
import ru.windcorp.progressia.common.util.Vectors;
|
||||||
|
import ru.windcorp.progressia.common.util.crash.CrashReports;
|
||||||
import ru.windcorp.progressia.common.world.Coordinates;
|
import ru.windcorp.progressia.common.world.Coordinates;
|
||||||
import ru.windcorp.progressia.common.world.WorldData;
|
import ru.windcorp.progressia.common.world.WorldData;
|
||||||
import ru.windcorp.progressia.common.world.block.BlockData;
|
import ru.windcorp.progressia.common.world.block.BlockData;
|
||||||
@ -21,50 +22,50 @@ import ru.windcorp.progressia.common.world.tile.TileData;
|
|||||||
import ru.windcorp.progressia.server.Server;
|
import ru.windcorp.progressia.server.Server;
|
||||||
|
|
||||||
public class ImplementedChangeTracker implements Changer {
|
public class ImplementedChangeTracker implements Changer {
|
||||||
|
|
||||||
public static interface ChangeImplementation {
|
public static interface ChangeImplementation {
|
||||||
void applyOnServer(WorldData world);
|
void applyOnServer(WorldData world);
|
||||||
Packet asPacket();
|
Packet asPacket();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class SetBlock
|
private static class SetBlock
|
||||||
extends PacketWorldChange
|
extends PacketWorldChange
|
||||||
implements ChangeImplementation {
|
implements ChangeImplementation {
|
||||||
|
|
||||||
private final Vec3i position = new Vec3i();
|
private final Vec3i position = new Vec3i();
|
||||||
private BlockData block;
|
private BlockData block;
|
||||||
|
|
||||||
public SetBlock() {
|
public SetBlock() {
|
||||||
super("Core", "SetBlock");
|
super("Core", "SetBlock");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void initialize(Vec3i position, BlockData block) {
|
public void initialize(Vec3i position, BlockData block) {
|
||||||
this.position.set(position.x, position.y, position.z);
|
this.position.set(position.x, position.y, position.z);
|
||||||
this.block = block;
|
this.block = block;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void applyOnServer(WorldData world) {
|
public void applyOnServer(WorldData world) {
|
||||||
Vec3i blockInChunk = Vectors.grab3i();
|
Vec3i blockInChunk = Vectors.grab3i();
|
||||||
Coordinates.convertInWorldToInChunk(position, blockInChunk);
|
Coordinates.convertInWorldToInChunk(position, blockInChunk);
|
||||||
|
|
||||||
world.getChunkByBlock(position).setBlock(blockInChunk, block);
|
world.getChunkByBlock(position).setBlock(blockInChunk, block);
|
||||||
|
|
||||||
Vectors.release(blockInChunk);
|
Vectors.release(blockInChunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void apply(WorldData world) {
|
public void apply(WorldData world) {
|
||||||
applyOnServer(world);
|
applyOnServer(world);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Packet asPacket() {
|
public Packet asPacket() {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class AddOrRemoveTile
|
private static class AddOrRemoveTile
|
||||||
extends PacketWorldChange
|
extends PacketWorldChange
|
||||||
implements ChangeImplementation {
|
implements ChangeImplementation {
|
||||||
@ -72,13 +73,13 @@ public class ImplementedChangeTracker implements Changer {
|
|||||||
private final Vec3i position = new Vec3i();
|
private final Vec3i position = new Vec3i();
|
||||||
private BlockFace face;
|
private BlockFace face;
|
||||||
private TileData tile;
|
private TileData tile;
|
||||||
|
|
||||||
private boolean shouldAdd;
|
private boolean shouldAdd;
|
||||||
|
|
||||||
public AddOrRemoveTile() {
|
public AddOrRemoveTile() {
|
||||||
super("Core", "AddOrRemoveTile");
|
super("Core", "AddOrRemoveTile");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void initialize(
|
public void initialize(
|
||||||
Vec3i position, BlockFace face,
|
Vec3i position, BlockFace face,
|
||||||
TileData tile,
|
TileData tile,
|
||||||
@ -89,52 +90,51 @@ public class ImplementedChangeTracker implements Changer {
|
|||||||
this.tile = tile;
|
this.tile = tile;
|
||||||
this.shouldAdd = shouldAdd;
|
this.shouldAdd = shouldAdd;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void applyOnServer(WorldData world) {
|
public void applyOnServer(WorldData world) {
|
||||||
Vec3i blockInChunk = Vectors.grab3i();
|
Vec3i blockInChunk = Vectors.grab3i();
|
||||||
Coordinates.convertInWorldToInChunk(position, blockInChunk);
|
Coordinates.convertInWorldToInChunk(position, blockInChunk);
|
||||||
|
|
||||||
List<TileData> tiles = world.getChunkByBlock(position)
|
List<TileData> tiles = world.getChunkByBlock(position).getTiles(blockInChunk, face);
|
||||||
.getTiles(blockInChunk, face);
|
|
||||||
|
|
||||||
if (shouldAdd) {
|
if (shouldAdd) {
|
||||||
tiles.add(tile);
|
tiles.add(tile);
|
||||||
} else {
|
} else {
|
||||||
tiles.remove(tile);
|
tiles.remove(tile);
|
||||||
}
|
}
|
||||||
|
|
||||||
Vectors.release(blockInChunk);
|
Vectors.release(blockInChunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void apply(WorldData world) {
|
public void apply(WorldData world) {
|
||||||
applyOnServer(world);
|
applyOnServer(world);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Packet asPacket() {
|
public Packet asPacket() {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class ChangeEntity implements ChangeImplementation {
|
private static class ChangeEntity implements ChangeImplementation {
|
||||||
|
|
||||||
private EntityData entity;
|
private EntityData entity;
|
||||||
private Change<?> change;
|
private Change<?> change;
|
||||||
|
|
||||||
private final PacketEntityChange packet = new PacketEntityChange();
|
private final PacketEntityChange packet = new PacketEntityChange();
|
||||||
|
|
||||||
public <T extends EntityData> void set(T entity, Change<T> change) {
|
public <T extends EntityData> void set(T entity, Change<T> change) {
|
||||||
this.entity = entity;
|
this.entity = entity;
|
||||||
this.change = change;
|
this.change = change;
|
||||||
|
|
||||||
packet.setEntityId(entity.getEntityId());
|
packet.setEntityId(entity.getEntityId());
|
||||||
try {
|
try {
|
||||||
entity.write(packet.getWriter(), IOContext.COMMS);
|
entity.write(packet.getWriter(), IOContext.COMMS);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException(e);
|
CrashReports.report(e, "__DOC__ME__");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,11 +142,11 @@ public class ImplementedChangeTracker implements Changer {
|
|||||||
@Override
|
@Override
|
||||||
public void applyOnServer(WorldData world) {
|
public void applyOnServer(WorldData world) {
|
||||||
((Change<EntityData>) change).change(entity);
|
((Change<EntityData>) change).change(entity);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
entity.write(packet.getWriter(), IOContext.COMMS);
|
entity.write(packet.getWriter(), IOContext.COMMS);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException("Entity could not be written", e);
|
CrashReports.report(e, "Entity could not be written");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,11 +154,11 @@ public class ImplementedChangeTracker implements Changer {
|
|||||||
public Packet asPacket() {
|
public Packet asPacket() {
|
||||||
return packet;
|
return packet;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private final List<ChangeImplementation> changes = new ArrayList<>(1024);
|
private final List<ChangeImplementation> changes = new ArrayList<>(1024);
|
||||||
|
|
||||||
private final LowOverheadCache<SetBlock> setBlockCache =
|
private final LowOverheadCache<SetBlock> setBlockCache =
|
||||||
new LowOverheadCache<>(SetBlock::new);
|
new LowOverheadCache<>(SetBlock::new);
|
||||||
|
|
||||||
@ -174,21 +174,21 @@ public class ImplementedChangeTracker implements Changer {
|
|||||||
change.initialize(pos, block);
|
change.initialize(pos, block);
|
||||||
changes.add(change);
|
changes.add(change);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addTile(Vec3i block, BlockFace face, TileData tile) {
|
public void addTile(Vec3i block, BlockFace face, TileData tile) {
|
||||||
AddOrRemoveTile change = addOrRemoveTileCache.grab();
|
AddOrRemoveTile change = addOrRemoveTileCache.grab();
|
||||||
change.initialize(block, face, tile, true);
|
change.initialize(block, face, tile, true);
|
||||||
changes.add(change);
|
changes.add(change);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeTile(Vec3i block, BlockFace face, TileData tile) {
|
public void removeTile(Vec3i block, BlockFace face, TileData tile) {
|
||||||
AddOrRemoveTile change = addOrRemoveTileCache.grab();
|
AddOrRemoveTile change = addOrRemoveTileCache.grab();
|
||||||
change.initialize(block, face, tile, false);
|
change.initialize(block, face, tile, false);
|
||||||
changes.add(change);
|
changes.add(change);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T extends EntityData> void changeEntity(
|
public <T extends EntityData> void changeEntity(
|
||||||
T entity, Change<T> change
|
T entity, Change<T> change
|
||||||
@ -197,7 +197,7 @@ public class ImplementedChangeTracker implements Changer {
|
|||||||
changeRecord.set(entity, change);
|
changeRecord.set(entity, change);
|
||||||
changes.add(changeRecord);
|
changes.add(changeRecord);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void applyChanges(Server server) {
|
public void applyChanges(Server server) {
|
||||||
changes.forEach(c -> c.applyOnServer(server.getWorld().getData()));
|
changes.forEach(c -> c.applyOnServer(server.getWorld().getData()));
|
||||||
changes.stream().map(ChangeImplementation::asPacket).filter(Objects::nonNull).forEach(
|
changes.stream().map(ChangeImplementation::asPacket).filter(Objects::nonNull).forEach(
|
||||||
@ -206,7 +206,7 @@ public class ImplementedChangeTracker implements Changer {
|
|||||||
changes.forEach(this::release);
|
changes.forEach(this::release);
|
||||||
changes.clear();
|
changes.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void release(ChangeImplementation c) {
|
private void release(ChangeImplementation c) {
|
||||||
if (c instanceof SetBlock) {
|
if (c instanceof SetBlock) {
|
||||||
setBlockCache.release((SetBlock) c);
|
setBlockCache.release((SetBlock) c);
|
||||||
|
Reference in New Issue
Block a user