mirror of
https://github.com/Grasscutters/Grasscutter.git
synced 2026-06-06 11:54:21 +08:00
Clean up .utils
This commit is contained in:
@@ -1,124 +0,0 @@
|
||||
package emu.grasscutter.utils;
|
||||
|
||||
import com.github.davidmoten.rtreemulti.geometry.Point;
|
||||
import dev.morphia.annotations.Entity;
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.SneakyThrows;
|
||||
|
||||
@Entity
|
||||
public final class GridPosition implements Serializable {
|
||||
private static final long serialVersionUID = -2001232300615923575L;
|
||||
|
||||
@Getter @Setter private int x;
|
||||
|
||||
@Getter @Setter private int z;
|
||||
|
||||
@Getter @Setter private int width;
|
||||
|
||||
public GridPosition() {}
|
||||
|
||||
public GridPosition(int x, int y, int width) {
|
||||
set(x, y, width);
|
||||
}
|
||||
|
||||
public GridPosition(GridPosition pos) {
|
||||
this.set(pos);
|
||||
}
|
||||
|
||||
public GridPosition(Position pos, int width) {
|
||||
this.set((int) (pos.getX() / width), (int) (pos.getZ() / width), width);
|
||||
}
|
||||
|
||||
public GridPosition(List<Integer> xzwidth) {
|
||||
this.width = xzwidth.get(2);
|
||||
this.z = xzwidth.get(1);
|
||||
this.x = xzwidth.get(0);
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
public GridPosition(String str) {
|
||||
var listOfParams = str.replace(" ", "").replace("(", "").replace(")", "").split(",");
|
||||
if (listOfParams.length != 3)
|
||||
throw new IOException("invalid size on GridPosition definition - ");
|
||||
try {
|
||||
this.x = Integer.parseInt(listOfParams[0]);
|
||||
this.z = Integer.parseInt(listOfParams[1]);
|
||||
this.width = Integer.parseInt(listOfParams[2]);
|
||||
} catch (NumberFormatException ignored) {
|
||||
throw new IOException("invalid number on GridPosition definition - ");
|
||||
}
|
||||
}
|
||||
|
||||
public GridPosition set(int x, int z) {
|
||||
this.x = x;
|
||||
this.z = z;
|
||||
return this;
|
||||
}
|
||||
|
||||
public GridPosition set(int x, int z, int width) {
|
||||
this.x = x;
|
||||
this.z = z;
|
||||
this.width = width;
|
||||
return this;
|
||||
}
|
||||
|
||||
// Deep copy
|
||||
public GridPosition set(GridPosition pos) {
|
||||
return this.set(pos.getX(), pos.getZ(), pos.getWidth());
|
||||
}
|
||||
|
||||
public GridPosition addClone(int x, int z) {
|
||||
GridPosition pos = clone();
|
||||
pos.x += x;
|
||||
pos.z += z;
|
||||
return pos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GridPosition clone() {
|
||||
return new GridPosition(x, z, width);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "(" + this.getX() + ", " + this.getZ() + ", " + this.getWidth() + ")";
|
||||
}
|
||||
|
||||
public int[] toIntArray() {
|
||||
return new int[] {x, z, width};
|
||||
}
|
||||
|
||||
public double[] toDoubleArray() {
|
||||
return new double[] {x, z};
|
||||
}
|
||||
|
||||
public int[] toXZIntArray() {
|
||||
return new int[] {x, z};
|
||||
}
|
||||
|
||||
public Point toPoint() {
|
||||
return Point.create(x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = x ^ (x >>> 32);
|
||||
result = 31 * result + (z ^ (z >>> 32));
|
||||
result = 31 * result + (width ^ (width >>> 32));
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null) return false;
|
||||
if (getClass() != o.getClass()) return false;
|
||||
GridPosition pos = (GridPosition) o;
|
||||
// field comparison
|
||||
return pos.x == x && pos.z == z && pos.width == width;
|
||||
}
|
||||
}
|
||||
@@ -8,44 +8,50 @@ import com.google.gson.stream.JsonReader;
|
||||
import com.google.gson.stream.JsonToken;
|
||||
import com.google.gson.stream.JsonWriter;
|
||||
import emu.grasscutter.data.common.DynamicFloat;
|
||||
import emu.grasscutter.game.world.GridPosition;
|
||||
import emu.grasscutter.game.world.Position;
|
||||
import it.unimi.dsi.fastutil.floats.FloatArrayList;
|
||||
import it.unimi.dsi.fastutil.ints.IntArrayList;
|
||||
import it.unimi.dsi.fastutil.ints.IntList;
|
||||
import lombok.val;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Objects;
|
||||
import lombok.val;
|
||||
|
||||
public class JsonAdapters {
|
||||
static class DynamicFloatAdapter extends TypeAdapter<DynamicFloat> {
|
||||
public interface JsonAdapters {
|
||||
class DynamicFloatAdapter extends TypeAdapter<DynamicFloat> {
|
||||
@Override
|
||||
public DynamicFloat read(JsonReader reader) throws IOException {
|
||||
switch (reader.peek()) {
|
||||
case STRING:
|
||||
case STRING -> {
|
||||
return new DynamicFloat(reader.nextString());
|
||||
case NUMBER:
|
||||
}
|
||||
case NUMBER -> {
|
||||
return new DynamicFloat((float) reader.nextDouble());
|
||||
case BOOLEAN:
|
||||
}
|
||||
case BOOLEAN -> {
|
||||
return new DynamicFloat(reader.nextBoolean());
|
||||
case BEGIN_ARRAY:
|
||||
}
|
||||
case BEGIN_ARRAY -> {
|
||||
reader.beginArray();
|
||||
val opStack = new ArrayList<DynamicFloat.StackOp>();
|
||||
while (reader.hasNext()) {
|
||||
opStack.add(
|
||||
switch (reader.peek()) {
|
||||
case STRING -> new DynamicFloat.StackOp(reader.nextString());
|
||||
case NUMBER -> new DynamicFloat.StackOp((float) reader.nextDouble());
|
||||
case BOOLEAN -> new DynamicFloat.StackOp(reader.nextBoolean());
|
||||
default -> throw new IOException(
|
||||
"Invalid DynamicFloat definition - " + reader.peek().name());
|
||||
});
|
||||
switch (reader.peek()) {
|
||||
case STRING -> new DynamicFloat.StackOp(reader.nextString());
|
||||
case NUMBER -> new DynamicFloat.StackOp((float) reader.nextDouble());
|
||||
case BOOLEAN -> new DynamicFloat.StackOp(reader.nextBoolean());
|
||||
default -> throw new IOException(
|
||||
"Invalid DynamicFloat definition - " + reader.peek().name());
|
||||
});
|
||||
}
|
||||
reader.endArray();
|
||||
return new DynamicFloat(opStack);
|
||||
default:
|
||||
throw new IOException("Invalid DynamicFloat definition - " + reader.peek().name());
|
||||
}
|
||||
default -> throw new IOException("Invalid DynamicFloat definition - " + reader.peek().name());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,7 +59,7 @@ public class JsonAdapters {
|
||||
public void write(JsonWriter writer, DynamicFloat f) {}
|
||||
}
|
||||
|
||||
static class IntListAdapter extends TypeAdapter<IntList> {
|
||||
class IntListAdapter extends TypeAdapter<IntList> {
|
||||
@Override
|
||||
public IntList read(JsonReader reader) throws IOException {
|
||||
if (Objects.requireNonNull(reader.peek()) == JsonToken.BEGIN_ARRAY) {
|
||||
@@ -72,12 +78,12 @@ public class JsonAdapters {
|
||||
public void write(JsonWriter writer, IntList l) throws IOException {
|
||||
writer.beginArray();
|
||||
for (val i : l) // .forEach() doesn't appreciate exceptions
|
||||
writer.value(i);
|
||||
writer.value(i);
|
||||
writer.endArray();
|
||||
}
|
||||
}
|
||||
|
||||
public static class ByteArrayAdapter extends TypeAdapter<byte[]> {
|
||||
public class ByteArrayAdapter extends TypeAdapter<byte[]> {
|
||||
@Override
|
||||
public void write(JsonWriter out, byte[] value) throws IOException {
|
||||
out.value(Utils.base64Encode(value));
|
||||
@@ -89,7 +95,7 @@ public class JsonAdapters {
|
||||
}
|
||||
}
|
||||
|
||||
static class GridPositionAdapter extends TypeAdapter<GridPosition> {
|
||||
class GridPositionAdapter extends TypeAdapter<GridPosition> {
|
||||
@Override
|
||||
public void write(JsonWriter out, GridPosition value) throws IOException {
|
||||
out.value("(" + value.getX() + ", " + value.getZ() + ", " + value.getWidth() + ")");
|
||||
@@ -113,17 +119,18 @@ public class JsonAdapters {
|
||||
}
|
||||
}
|
||||
|
||||
static class PositionAdapter extends TypeAdapter<Position> {
|
||||
class PositionAdapter extends TypeAdapter<Position> {
|
||||
@Override
|
||||
public Position read(JsonReader reader) throws IOException {
|
||||
switch (reader.peek()) {
|
||||
case BEGIN_ARRAY: // "pos": [x,y,z]
|
||||
case BEGIN_ARRAY -> { // "pos": [x,y,z]
|
||||
reader.beginArray();
|
||||
val array = new FloatArrayList(3);
|
||||
while (reader.hasNext()) array.add(reader.nextInt());
|
||||
reader.endArray();
|
||||
return new Position(array);
|
||||
case BEGIN_OBJECT: // "pos": {"x": x, "y": y, "z": z}
|
||||
}
|
||||
case BEGIN_OBJECT -> { // "pos": {"x": x, "y": y, "z": z}
|
||||
float x = 0f;
|
||||
float y = 0f;
|
||||
float z = 0f;
|
||||
@@ -139,8 +146,8 @@ public class JsonAdapters {
|
||||
}
|
||||
reader.endObject();
|
||||
return new Position(x, y, z);
|
||||
default:
|
||||
throw new IOException("Invalid Position definition - " + reader.peek().name());
|
||||
}
|
||||
default -> throw new IOException("Invalid Position definition - " + reader.peek().name());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,7 +161,7 @@ public class JsonAdapters {
|
||||
}
|
||||
}
|
||||
|
||||
static class EnumTypeAdapterFactory implements TypeAdapterFactory {
|
||||
class EnumTypeAdapterFactory implements TypeAdapterFactory {
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
|
||||
Class<T> enumClass = (Class<T>) type.getRawType();
|
||||
@@ -186,16 +193,13 @@ public class JsonAdapters {
|
||||
}
|
||||
}
|
||||
|
||||
return new TypeAdapter<T>() {
|
||||
return new TypeAdapter<>() {
|
||||
public T read(JsonReader reader) throws IOException {
|
||||
switch (reader.peek()) {
|
||||
case STRING:
|
||||
return map.get(reader.nextString());
|
||||
case NUMBER:
|
||||
return map.get(String.valueOf(reader.nextInt()));
|
||||
default:
|
||||
throw new IOException("Invalid Enum definition - " + reader.peek().name());
|
||||
}
|
||||
return switch (reader.peek()) {
|
||||
case STRING -> map.get(reader.nextString());
|
||||
case NUMBER -> map.get(String.valueOf(reader.nextInt()));
|
||||
default -> throw new IOException("Invalid Enum definition - " + reader.peek().name());
|
||||
};
|
||||
}
|
||||
|
||||
public void write(JsonWriter writer, T value) throws IOException {
|
||||
|
||||
@@ -3,6 +3,8 @@ package emu.grasscutter.utils;
|
||||
import com.google.gson.*;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import emu.grasscutter.data.common.DynamicFloat;
|
||||
import emu.grasscutter.game.world.GridPosition;
|
||||
import emu.grasscutter.game.world.Position;
|
||||
import emu.grasscutter.utils.JsonAdapters.*;
|
||||
import it.unimi.dsi.fastutil.ints.IntList;
|
||||
import java.io.FileInputStream;
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
package emu.grasscutter.utils;
|
||||
|
||||
import dev.morphia.annotations.Entity;
|
||||
import dev.morphia.annotations.Transient;
|
||||
import emu.grasscutter.game.world.Scene;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Entity
|
||||
public class Location extends Position {
|
||||
@Transient @Getter @Setter private Scene scene;
|
||||
|
||||
public Location(Scene scene, Position position) {
|
||||
this.set(position);
|
||||
|
||||
this.scene = scene;
|
||||
}
|
||||
|
||||
public Location(Scene scene, float x, float y) {
|
||||
this.set(x, y);
|
||||
|
||||
this.scene = scene;
|
||||
}
|
||||
|
||||
public Location(Scene scene, float x, float y, float z) {
|
||||
this.set(x, y, z);
|
||||
|
||||
this.scene = scene;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Location clone() {
|
||||
return new Location(this.scene, super.clone());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%s:%s,%s,%s", this.scene.getId(), this.getX(), this.getY(), this.getZ());
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
package emu.grasscutter.utils;
|
||||
|
||||
public class MessageHandler {
|
||||
private String message;
|
||||
|
||||
public MessageHandler() {
|
||||
this.message = "";
|
||||
}
|
||||
|
||||
public void append(String message) {
|
||||
this.message += message + "\r\n\r\n";
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return this.message;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
}
|
||||
@@ -1,200 +0,0 @@
|
||||
package emu.grasscutter.utils;
|
||||
|
||||
import com.github.davidmoten.rtreemulti.geometry.Point;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import dev.morphia.annotations.Entity;
|
||||
import emu.grasscutter.net.proto.VectorOuterClass.Vector;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
@Entity
|
||||
public class Position implements Serializable {
|
||||
private static final long serialVersionUID = -2001232313615923575L;
|
||||
|
||||
public static final Position ZERO = new Position(0, 0, 0);
|
||||
public static final Position IDENTITY = new Position(0, 0);
|
||||
|
||||
@SerializedName(
|
||||
value = "x",
|
||||
alternate = {"_x", "X"})
|
||||
@Getter
|
||||
@Setter
|
||||
private float x;
|
||||
|
||||
@SerializedName(
|
||||
value = "y",
|
||||
alternate = {"_y", "Y"})
|
||||
@Getter
|
||||
@Setter
|
||||
private float y;
|
||||
|
||||
@SerializedName(
|
||||
value = "z",
|
||||
alternate = {"_z", "Z"})
|
||||
@Getter
|
||||
@Setter
|
||||
private float z;
|
||||
|
||||
public Position() {}
|
||||
|
||||
public Position(float x, float y) {
|
||||
set(x, y);
|
||||
}
|
||||
|
||||
public Position(float x, float y, float z) {
|
||||
set(x, y, z);
|
||||
}
|
||||
|
||||
public Position(List<Float> xyz) {
|
||||
switch (xyz.size()) {
|
||||
default: // Might want to error on excess elements, but maybe we want to extend to 3+3
|
||||
// representation later.
|
||||
case 3:
|
||||
this.z = xyz.get(2); // Fall-through
|
||||
case 2:
|
||||
this.y = xyz.get(1); // Fall-through
|
||||
case 1:
|
||||
this.y = xyz.get(0); // pointless fall-through
|
||||
case 0:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public Position(String p) {
|
||||
String[] split = p.split(",");
|
||||
if (split.length >= 2) {
|
||||
this.x = Float.parseFloat(split[0]);
|
||||
this.y = Float.parseFloat(split[1]);
|
||||
}
|
||||
if (split.length >= 3) {
|
||||
this.z = Float.parseFloat(split[2]);
|
||||
}
|
||||
}
|
||||
|
||||
public Position(Vector vector) {
|
||||
this.set(vector);
|
||||
}
|
||||
|
||||
public Position(Position pos) {
|
||||
this.set(pos);
|
||||
}
|
||||
|
||||
public Position set(float x, float y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
return this;
|
||||
}
|
||||
|
||||
// Deep copy
|
||||
public Position set(Position pos) {
|
||||
return this.set(pos.getX(), pos.getY(), pos.getZ());
|
||||
}
|
||||
|
||||
public Position set(Vector pos) {
|
||||
return this.set(pos.getX(), pos.getY(), pos.getZ());
|
||||
}
|
||||
|
||||
public Position set(float x, float y, float z) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Position add(Position add) {
|
||||
this.x += add.getX();
|
||||
this.y += add.getY();
|
||||
this.z += add.getZ();
|
||||
return this;
|
||||
}
|
||||
|
||||
public Position addX(float d) {
|
||||
this.x += d;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Position addY(float d) {
|
||||
this.y += d;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Position addZ(float d) {
|
||||
this.z += d;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Position subtract(Position sub) {
|
||||
this.x -= sub.getX();
|
||||
this.y -= sub.getY();
|
||||
this.z -= sub.getZ();
|
||||
return this;
|
||||
}
|
||||
|
||||
/** In radians */
|
||||
public Position translate(float dist, float angle) {
|
||||
this.x += dist * Math.sin(angle);
|
||||
this.y += dist * Math.cos(angle);
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean equal2d(Position other) {
|
||||
// Y is height
|
||||
return getX() == other.getX() && getZ() == other.getZ();
|
||||
}
|
||||
|
||||
public boolean equal3d(Position other) {
|
||||
return getX() == other.getX() && getY() == other.getY() && getZ() == other.getZ();
|
||||
}
|
||||
|
||||
public double computeDistance(Position b) {
|
||||
double detX = getX() - b.getX();
|
||||
double detY = getY() - b.getY();
|
||||
double detZ = getZ() - b.getZ();
|
||||
return Math.sqrt(detX * detX + detY * detY + detZ * detZ);
|
||||
}
|
||||
|
||||
public Position nearby2d(float range) {
|
||||
Position position = clone();
|
||||
position.z += Utils.randomFloatRange(-range, range);
|
||||
position.x += Utils.randomFloatRange(-range, range);
|
||||
return position;
|
||||
}
|
||||
|
||||
public Position translateWithDegrees(float dist, float angle) {
|
||||
angle = (float) Math.toRadians(angle);
|
||||
this.x += dist * Math.sin(angle);
|
||||
this.y += -dist * Math.cos(angle);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position clone() {
|
||||
return new Position(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "(" + this.getX() + ", " + this.getY() + ", " + this.getZ() + ")";
|
||||
}
|
||||
|
||||
public Vector toProto() {
|
||||
return Vector.newBuilder().setX(this.getX()).setY(this.getY()).setZ(this.getZ()).build();
|
||||
}
|
||||
|
||||
public Point toPoint() {
|
||||
return Point.create(x, y, z);
|
||||
}
|
||||
|
||||
/** To XYZ array for Spatial Index */
|
||||
public double[] toDoubleArray() {
|
||||
return new double[] {x, y, z};
|
||||
}
|
||||
|
||||
/** To XZ array for Spatial Index (Blocks) */
|
||||
public double[] toXZDoubleArray() {
|
||||
return new double[] {x, z};
|
||||
}
|
||||
}
|
||||
@@ -1,22 +1,23 @@
|
||||
package emu.grasscutter.utils;
|
||||
|
||||
import static emu.grasscutter.config.Configuration.*;
|
||||
|
||||
import ch.qos.logback.classic.Level;
|
||||
import ch.qos.logback.classic.Logger;
|
||||
import emu.grasscutter.BuildConfig;
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.net.packet.PacketOpcodesUtils;
|
||||
import emu.grasscutter.tools.Dumpers;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static emu.grasscutter.config.Configuration.*;
|
||||
|
||||
/** A parser for start-up arguments. */
|
||||
public final class StartupArguments {
|
||||
public interface StartupArguments {
|
||||
/* A map of parameter -> argument handler. */
|
||||
private static final Map<String, Function<String, Boolean>> argumentHandlers =
|
||||
Map<String, Function<String, Boolean>> argumentHandlers =
|
||||
new HashMap<>() {
|
||||
{
|
||||
putAll(
|
||||
@@ -74,17 +75,13 @@ public final class StartupArguments {
|
||||
}
|
||||
};
|
||||
|
||||
private StartupArguments() {
|
||||
// This class is not meant to be instantiated.
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the provided start-up arguments.
|
||||
*
|
||||
* @param args The application start-up arguments.
|
||||
* @return If the application should exit.
|
||||
*/
|
||||
public static boolean parse(String[] args) {
|
||||
static boolean parse(String[] args) {
|
||||
boolean exitEarly = false;
|
||||
|
||||
// Parse the arguments.
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package emu.grasscutter.utils;
|
||||
|
||||
import static emu.grasscutter.utils.Utils.nonRegexSplit;
|
||||
|
||||
import com.google.gson.*;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import emu.grasscutter.Grasscutter;
|
||||
@@ -9,6 +7,8 @@ import it.unimi.dsi.fastutil.Pair;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectRBTreeMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectSortedMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntArrayMap;
|
||||
import lombok.val;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
@@ -19,11 +19,12 @@ import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.IntStream;
|
||||
import java.util.stream.Stream;
|
||||
import lombok.val;
|
||||
|
||||
import static emu.grasscutter.utils.Utils.nonRegexSplit;
|
||||
|
||||
// Throughout this file, commented System.out.println debug log calls are left in.
|
||||
// This is because the default logger will deadlock when operating on parallel streams.
|
||||
public class TsvUtils {
|
||||
public final class TsvUtils {
|
||||
private static final Map<Type, Object> defaultValues =
|
||||
Map.ofEntries(
|
||||
// Map.entry(String.class, null), // builder hates null values
|
||||
@@ -679,4 +680,8 @@ public class TsvUtils {
|
||||
return map;
|
||||
}
|
||||
}
|
||||
|
||||
private TsvUtils() {
|
||||
// No instantiation.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
package emu.grasscutter.utils;
|
||||
|
||||
import static emu.grasscutter.utils.FileUtils.getResourcePath;
|
||||
import static emu.grasscutter.utils.Language.translate;
|
||||
import static emu.grasscutter.utils.lang.Language.translate;
|
||||
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.config.ConfigContainer;
|
||||
import emu.grasscutter.data.DataLoader;
|
||||
import emu.grasscutter.game.world.Position;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufUtil;
|
||||
import io.netty.buffer.Unpooled;
|
||||
|
||||
+7
-7
@@ -1,16 +1,16 @@
|
||||
package emu.grasscutter.utils;
|
||||
package emu.grasscutter.utils.helpers;
|
||||
|
||||
public class ByteHelper {
|
||||
public static byte[] changeBytes(byte[] a) {
|
||||
byte[] b = new byte[a.length];
|
||||
for (int i = 0; i < a.length; i++) {
|
||||
public interface ByteHelper {
|
||||
static byte[] changeBytes(byte[] a) {
|
||||
var b = new byte[a.length];
|
||||
for (var i = 0; i < a.length; i++) {
|
||||
b[i] = a[a.length - i - 1];
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
public static byte[] longToBytes(long x) {
|
||||
byte[] bytes = new byte[8];
|
||||
static byte[] longToBytes(long x) {
|
||||
var bytes = new byte[8];
|
||||
bytes[0] = (byte) (x >> 56);
|
||||
bytes[1] = (byte) (x >> 48);
|
||||
bytes[2] = (byte) (x >> 40);
|
||||
+5
-5
@@ -1,11 +1,11 @@
|
||||
package emu.grasscutter.utils;
|
||||
package emu.grasscutter.utils.helpers;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
|
||||
public final class DateHelper {
|
||||
public static Date onlyYearMonthDay(Date now) {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
public interface DateHelper {
|
||||
static Date onlyYearMonthDay(Date now) {
|
||||
var calendar = Calendar.getInstance();
|
||||
calendar.setTime(now);
|
||||
calendar.set(Calendar.HOUR_OF_DAY, 0);
|
||||
calendar.set(Calendar.MINUTE, 0);
|
||||
@@ -14,7 +14,7 @@ public final class DateHelper {
|
||||
return calendar.getTime();
|
||||
}
|
||||
|
||||
public static int getUnixTime(Date localDateTime) {
|
||||
static int getUnixTime(Date localDateTime) {
|
||||
return (int) (localDateTime.getTime() / 1000L);
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -1,10 +1,10 @@
|
||||
package emu.grasscutter.utils;
|
||||
package emu.grasscutter.utils.helpers;
|
||||
|
||||
import emu.grasscutter.game.props.PlayerProperty;
|
||||
import emu.grasscutter.net.proto.PropValueOuterClass.PropValue;
|
||||
|
||||
public final class ProtoHelper {
|
||||
public static PropValue newPropValue(PlayerProperty key, int value) {
|
||||
public interface ProtoHelper {
|
||||
static PropValue newPropValue(PlayerProperty key, int value) {
|
||||
return PropValue.newBuilder().setType(key.getId()).setIval(value).setVal(value).build();
|
||||
}
|
||||
}
|
||||
+9
-6
@@ -1,8 +1,4 @@
|
||||
package emu.grasscutter.utils;
|
||||
|
||||
import static emu.grasscutter.config.Configuration.FALLBACK_LANGUAGE;
|
||||
import static emu.grasscutter.utils.FileUtils.getCachePath;
|
||||
import static emu.grasscutter.utils.FileUtils.getResourcePath;
|
||||
package emu.grasscutter.utils.lang;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
@@ -11,12 +7,16 @@ import emu.grasscutter.data.GameData;
|
||||
import emu.grasscutter.data.ResourceLoader;
|
||||
import emu.grasscutter.data.excels.achievement.AchievementData;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.utils.JsonUtils;
|
||||
import emu.grasscutter.utils.Utils;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
|
||||
import it.unimi.dsi.fastutil.ints.IntSet;
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
@@ -28,7 +28,10 @@ import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import static emu.grasscutter.config.Configuration.FALLBACK_LANGUAGE;
|
||||
import static emu.grasscutter.utils.FileUtils.getCachePath;
|
||||
import static emu.grasscutter.utils.FileUtils.getResourcePath;
|
||||
|
||||
public final class Language {
|
||||
private static final Map<String, Language> cachedLanguages = new ConcurrentHashMap<>();
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package emu.grasscutter.utils;
|
||||
package emu.grasscutter.utils.objects;
|
||||
|
||||
import emu.grasscutter.server.event.Event;
|
||||
|
||||
+4
-5
@@ -1,16 +1,15 @@
|
||||
package emu.grasscutter.utils;
|
||||
package emu.grasscutter.utils.objects;
|
||||
|
||||
import ch.qos.logback.classic.spi.ILoggingEvent;
|
||||
import ch.qos.logback.core.ConsoleAppender;
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class JlineLogbackAppender extends ConsoleAppender<ILoggingEvent> {
|
||||
public final class JLineLogbackAppender extends ConsoleAppender<ILoggingEvent> {
|
||||
@Override
|
||||
protected void append(ILoggingEvent eventObject) {
|
||||
if (!started) {
|
||||
return;
|
||||
}
|
||||
if (!this.started) return;
|
||||
|
||||
Arrays.stream(new String(encoder.encode(eventObject)).split("\n\r"))
|
||||
.forEach(Grasscutter.getConsole()::printAbove);
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package emu.grasscutter.utils;
|
||||
package emu.grasscutter.utils.objects;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
package emu.grasscutter.utils;
|
||||
package emu.grasscutter.utils.objects;
|
||||
|
||||
import ch.qos.logback.classic.spi.ILoggingEvent;
|
||||
import ch.qos.logback.core.AppenderBase;
|
||||
@@ -6,7 +6,7 @@ import ch.qos.logback.core.encoder.Encoder;
|
||||
import emu.grasscutter.server.event.internal.ServerLogEvent;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
public class ServerLogEventAppender<E> extends AppenderBase<E> {
|
||||
public final class ServerLogEventAppender<E> extends AppenderBase<E> {
|
||||
protected Encoder<E> encoder;
|
||||
|
||||
@Override
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package emu.grasscutter.utils;
|
||||
package emu.grasscutter.utils.objects;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package emu.grasscutter.utils;
|
||||
package emu.grasscutter.utils.objects;
|
||||
|
||||
import java.util.NavigableMap;
|
||||
import java.util.TreeMap;
|
||||
@@ -0,0 +1,235 @@
|
||||
package emu.grasscutter.utils.objects.text;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/* Text style container. */
|
||||
@Builder
|
||||
@Data
|
||||
public final class Style {
|
||||
private static final Map<Character, String> unity = new HashMap<>();
|
||||
private static final Map<Character, String> ansi = new HashMap<>();
|
||||
|
||||
static {
|
||||
// Add the Minecraft color codes to the color map.
|
||||
unity.put('0', "#000000"); // Black
|
||||
unity.put('1', "#0000AA"); // Dark Blue
|
||||
unity.put('2', "#00AA00"); // Dark Green
|
||||
unity.put('3', "#00AAAA"); // Dark Aqua
|
||||
unity.put('4', "#AA0000"); // Dark Red
|
||||
unity.put('5', "#AA00AA"); // Dark Purple
|
||||
unity.put('6', "#FFAA00"); // Gold
|
||||
unity.put('7', "#AAAAAA"); // Gray
|
||||
unity.put('8', "#555555"); // Dark Gray
|
||||
unity.put('9', "#5555FF"); // Blue
|
||||
unity.put('a', "#55FF55"); // Green
|
||||
unity.put('b', "#55FFFF"); // Aqua
|
||||
unity.put('c', "#FF5555"); // Red
|
||||
unity.put('d', "#FF55FF"); // Light Purple
|
||||
unity.put('e', "#FFFF55"); // Yellow
|
||||
unity.put('f', "#FFFFFF"); // White
|
||||
|
||||
ansi.put('0', "\u001B[30m"); // Black
|
||||
ansi.put('1', "\u001B[34m"); // Dark Blue
|
||||
ansi.put('2', "\u001B[32m"); // Dark Green
|
||||
ansi.put('3', "\u001B[36m"); // Dark Aqua
|
||||
ansi.put('4', "\u001B[31m"); // Dark Red
|
||||
ansi.put('5', "\u001B[35m"); // Dark Purple
|
||||
ansi.put('6', "\u001B[33m"); // Gold
|
||||
ansi.put('7', "\u001B[37m"); // Gray
|
||||
ansi.put('8', "\u001B[90m"); // Dark Gray
|
||||
ansi.put('9', "\u001B[94m"); // Blue
|
||||
ansi.put('a', "\u001B[92m"); // Green
|
||||
ansi.put('b', "\u001B[96m"); // Aqua
|
||||
ansi.put('c', "\u001B[91m"); // Red
|
||||
ansi.put('d', "\u001B[95m"); // Light Purple
|
||||
ansi.put('e', "\u001B[93m"); // Yellow
|
||||
ansi.put('f', "\u001B[97m"); // White
|
||||
}
|
||||
|
||||
@Builder.Default private int size = -1; // Unity only.
|
||||
@Builder.Default private boolean bold = false; // Unity only.
|
||||
@Builder.Default private boolean italic = false; // Unity only.
|
||||
|
||||
@Builder.Default private Color color = null;
|
||||
|
||||
/**
|
||||
* Replaces detected sequences of &color with the specified text.
|
||||
*
|
||||
* @param input The input text.
|
||||
* @return The replaced text.
|
||||
*/
|
||||
private String replaceUnity(String input) {
|
||||
// Thanks ChatGPT! (from ChatGPT)
|
||||
// Check if the input string is null or empty
|
||||
if (input == null || input.isEmpty()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
var output = new StringBuilder();
|
||||
var i = 0;
|
||||
while (i < input.length()) {
|
||||
var c = input.charAt(i);
|
||||
if (c == '&') {
|
||||
// Check if the Minecraft color code is valid
|
||||
if (i + 1 < input.length() && unity.containsKey(input.charAt(i + 1))) {
|
||||
// Append the Unity color code
|
||||
output.append("<color=").append(unity.get(input.charAt(i + 1))).append(">");
|
||||
|
||||
// Move the index past the Minecraft color code
|
||||
i += 2;
|
||||
|
||||
// Find the end of the color code span
|
||||
var end = input.indexOf('&', i);
|
||||
if (end == -1) {
|
||||
end = input.length();
|
||||
}
|
||||
|
||||
// Append the text within the color code span
|
||||
output.append(input, i, end);
|
||||
|
||||
// Append the closing tag for the Unity color code
|
||||
output.append("</color>");
|
||||
|
||||
// Move the index to the end of the color code span
|
||||
i = end;
|
||||
} else {
|
||||
// Invalid Minecraft color code, treat it as regular text
|
||||
output.append(c);
|
||||
i++;
|
||||
}
|
||||
} else {
|
||||
// Append regular text
|
||||
output.append(c);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
return output.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces detected sequences of &color with the specified text.
|
||||
*
|
||||
* @param input The input text.
|
||||
* @return The replaced text.
|
||||
*/
|
||||
private String replaceTerminal(String input) {
|
||||
// Check if the input string is null or empty
|
||||
if (input == null || input.isEmpty()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
var output = new StringBuilder();
|
||||
var i = 0;
|
||||
while (i < input.length()) {
|
||||
var c = input.charAt(i);
|
||||
if (c == '&') {
|
||||
// Check if the Minecraft color code is valid
|
||||
if (i + 1 < input.length() && ansi.containsKey(input.charAt(i + 1))) {
|
||||
// Append the ANSI escape code
|
||||
output.append(ansi.get(input.charAt(i + 1)));
|
||||
|
||||
// Move the index past the Minecraft color code
|
||||
i += 2;
|
||||
|
||||
// Find the end of the color code span
|
||||
var end = input.indexOf('&', i);
|
||||
if (end == -1) {
|
||||
end = input.length();
|
||||
}
|
||||
|
||||
// Append the text within the color code span
|
||||
output.append(input, i, end);
|
||||
|
||||
// Reset the color back to default
|
||||
output.append("\u001B[0m");
|
||||
|
||||
// Move the index to the end of the color code span
|
||||
i = end;
|
||||
} else {
|
||||
// Invalid Minecraft color code, treat it as regular text
|
||||
output.append(c);
|
||||
i++;
|
||||
}
|
||||
} else {
|
||||
// Append regular text
|
||||
output.append(c);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
return output.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps the text in the style. Formatted for Unity clients.
|
||||
*
|
||||
* @param text The text to wrap.
|
||||
* @return The wrapped text.
|
||||
*/
|
||||
public String toUnity(String text) {
|
||||
var builder = new StringBuilder();
|
||||
|
||||
// Set the size.
|
||||
if (this.size != -1) {
|
||||
builder.append("<size=").append(this.size).append(">");
|
||||
}
|
||||
|
||||
// Set the color.
|
||||
if (this.color != null) {
|
||||
builder
|
||||
.append("<color=")
|
||||
.append(
|
||||
String.format(
|
||||
"#%02x%02x%02x",
|
||||
this.color.getRed(), this.color.getGreen(), this.color.getBlue()))
|
||||
.append(">");
|
||||
}
|
||||
|
||||
// Set the boldness.
|
||||
if (this.bold) builder.append("<b>");
|
||||
// Set the italicness.
|
||||
if (this.italic) builder.append("<i>");
|
||||
|
||||
// Append the text.
|
||||
builder.append(this.replaceUnity(text));
|
||||
|
||||
// Close the tags.
|
||||
if (this.italic) builder.append("</i>");
|
||||
if (this.bold) builder.append("</b>");
|
||||
if (this.color != null) builder.append("</color>");
|
||||
if (this.size != -1) builder.append("</size>");
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps the text in the style. Formatted for terminal clients.
|
||||
*
|
||||
* @param text The text to wrap.
|
||||
* @return The wrapped text.
|
||||
*/
|
||||
public String toTerminal(String text) {
|
||||
// Check for color.
|
||||
if (this.color == null) return this.replaceTerminal(text);
|
||||
|
||||
// Convert the color to an ANSI color.
|
||||
var ansiColor =
|
||||
this.color.getRed() > 127
|
||||
? this.color.getGreen() > 127
|
||||
? this.color.getBlue() > 127 ? 15 : 11
|
||||
: this.color.getBlue() > 127 ? 13 : 9
|
||||
: this.color.getGreen() > 127
|
||||
? this.color.getBlue() > 127 ? 14 : 10
|
||||
: this.color.getBlue() > 127 ? 12 : 8;
|
||||
|
||||
// Return the text with the ANSI color.
|
||||
// Reset the color at the end.
|
||||
return "\u001B[38;5;" + ansiColor + "m" + this.replaceTerminal(text) + "\u001B[0m";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
package emu.grasscutter.utils.objects.text;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
/* An instance of text. */
|
||||
public final class Text {
|
||||
/**
|
||||
* Creates a new rich instance of text.
|
||||
*
|
||||
* @param text The text to use.
|
||||
* @return The new instance of text.
|
||||
*/
|
||||
public static Text of(String text) {
|
||||
return new Text(text, false);
|
||||
}
|
||||
|
||||
@Getter private final boolean raw;
|
||||
private final Style.StyleBuilder style = Style.builder();
|
||||
|
||||
@Setter private String text;
|
||||
|
||||
/**
|
||||
* Creates a new rich instance of text.
|
||||
*
|
||||
* @param text The text to use.
|
||||
*/
|
||||
public Text(String text) {
|
||||
this.raw = false;
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance of text.
|
||||
*
|
||||
* @param text The text to use.
|
||||
* @param raw Whether the text is raw.
|
||||
*/
|
||||
public Text(String text, boolean raw) {
|
||||
this.raw = raw;
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the size of the text.
|
||||
*
|
||||
* @param size The size of the text.
|
||||
* @return This object.
|
||||
*/
|
||||
public Text size(int size) {
|
||||
this.style.size(size);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the color of the text.
|
||||
*
|
||||
* @param color The color of the text.
|
||||
* @return This object.
|
||||
*/
|
||||
public Text color(Color color) {
|
||||
this.style.color(color);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the boldness of the text.
|
||||
*
|
||||
* @param bold Whether the text is bold.
|
||||
* @return This object.
|
||||
*/
|
||||
public Text bold(boolean bold) {
|
||||
this.style.bold(bold);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the italicness of the text.
|
||||
*
|
||||
* @param italic Whether the text is italic.
|
||||
* @return This object.
|
||||
*/
|
||||
public Text italic(boolean italic) {
|
||||
this.style.italic(italic);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts this object to a string. Converts to a console or Unity format.
|
||||
*
|
||||
* @param console Whether to convert the text for the console.
|
||||
* @return The converted string.
|
||||
*/
|
||||
public String toString(boolean console) {
|
||||
// Pull instances of style and text.
|
||||
var style = this.style.build();
|
||||
var text = this.text;
|
||||
|
||||
return console ? style.toTerminal(text) : style.toUnity(text);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user