Compare commits
17 Commits
v0.2.0-bet
...
v0.2.0-bet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a6cf977c5f | ||
|
|
8ed23bc8f3 | ||
|
|
7034995878 | ||
|
|
ca3d776562 | ||
|
|
1a077389c2 | ||
|
|
49bcc60cf5 | ||
|
|
8b1f31ade8 | ||
|
|
4d88e04e3c | ||
|
|
33889c3850 | ||
|
|
37ac3003cb | ||
|
|
28128d06c1 | ||
|
|
6f9620787b | ||
|
|
cbf6c118dc | ||
|
|
d44fa1f8aa | ||
|
|
3d9ae3f018 | ||
|
|
d24f6c2874 | ||
|
|
f190cdd8cb |
4
.github/workflows/build.yml
vendored
4
.github/workflows/build.yml
vendored
@@ -31,8 +31,8 @@ jobs:
|
|||||||
key: ${{ runner.os }}-project-local-gradle-caches-${{ hashFiles('**/libs.versions.toml', '**/*.gradle*', '**/gradle-wrapper.properties') }}
|
key: ${{ runner.os }}-project-local-gradle-caches-${{ hashFiles('**/libs.versions.toml', '**/*.gradle*', '**/gradle-wrapper.properties') }}
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
${{ runner.os }}-project-local-gradle-caches-
|
${{ runner.os }}-project-local-gradle-caches-
|
||||||
- name: "setup concurrentutil"
|
- name: "setup dependencies"
|
||||||
run: ./installConcurrentUtil.sh
|
run: ./install_deps.sh
|
||||||
- name: "execute gradle build"
|
- name: "execute gradle build"
|
||||||
run: ./gradlew build
|
run: ./gradlew build
|
||||||
- name: Determine Snapshot Status
|
- name: Determine Snapshot Status
|
||||||
|
|||||||
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -1,3 +1,6 @@
|
|||||||
[submodule "ConcurrentUtil"]
|
[submodule "ConcurrentUtil"]
|
||||||
path = ConcurrentUtil
|
path = ConcurrentUtil
|
||||||
url = https://github.com/Spottedleaf/ConcurrentUtil.git
|
url = https://github.com/Spottedleaf/ConcurrentUtil.git
|
||||||
|
[submodule "YamlConfig"]
|
||||||
|
path = YamlConfig
|
||||||
|
url = https://github.com/Spottedleaf/YamlConfig.git
|
||||||
|
|||||||
1
YamlConfig
Submodule
1
YamlConfig
Submodule
Submodule YamlConfig added at 67552e7707
@@ -23,6 +23,7 @@ dependencies {
|
|||||||
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
|
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
|
||||||
|
|
||||||
api("ca.spottedleaf:concurrentutil:${rootProject.concurrentutil_version}")
|
api("ca.spottedleaf:concurrentutil:${rootProject.concurrentutil_version}")
|
||||||
|
api("ca.spottedleaf:yamlconfig:${rootProject.yamlconfig_version}")
|
||||||
api("org.yaml:snakeyaml:${rootProject.snakeyaml_version}")
|
api("org.yaml:snakeyaml:${rootProject.snakeyaml_version}")
|
||||||
|
|
||||||
modImplementation "me.shedaniel.cloth:cloth-config:${rootProject.cloth_version}"
|
modImplementation "me.shedaniel.cloth:cloth-config:${rootProject.cloth_version}"
|
||||||
@@ -48,6 +49,7 @@ allprojects {
|
|||||||
mavenLocal {
|
mavenLocal {
|
||||||
mavenContent {
|
mavenContent {
|
||||||
includeModule("ca.spottedleaf", "concurrentutil")
|
includeModule("ca.spottedleaf", "concurrentutil")
|
||||||
|
includeModule("ca.spottedleaf", "yamlconfig")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
maven {
|
maven {
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ dependencies {
|
|||||||
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
|
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
|
||||||
|
|
||||||
libs("ca.spottedleaf:concurrentutil:${rootProject.concurrentutil_version}")
|
libs("ca.spottedleaf:concurrentutil:${rootProject.concurrentutil_version}")
|
||||||
|
libs("ca.spottedleaf:yamlconfig:${rootProject.yamlconfig_version}")
|
||||||
libs("org.yaml:snakeyaml:${rootProject.snakeyaml_version}")
|
libs("org.yaml:snakeyaml:${rootProject.snakeyaml_version}")
|
||||||
|
|
||||||
modImplementation "me.shedaniel.cloth:cloth-config-fabric:${rootProject.cloth_version}"
|
modImplementation "me.shedaniel.cloth:cloth-config-fabric:${rootProject.cloth_version}"
|
||||||
@@ -43,6 +44,7 @@ shadowJar {
|
|||||||
destinationDirectory = layout.buildDirectory.dir("libs")
|
destinationDirectory = layout.buildDirectory.dir("libs")
|
||||||
configurations = [project.configurations.shadow]
|
configurations = [project.configurations.shadow]
|
||||||
relocate 'ca.spottedleaf.concurrentutil', 'ca.spottedleaf.moonrise.libs.ca.spottedleaf.concurrentutil'
|
relocate 'ca.spottedleaf.concurrentutil', 'ca.spottedleaf.moonrise.libs.ca.spottedleaf.concurrentutil'
|
||||||
|
relocate 'ca.spottedleaf.yamlconfig', 'ca.spottedleaf.moonrise.libs.ca.spottedleaf.yamlconfig'
|
||||||
relocate 'org.yaml.snakeyaml', 'ca.spottedleaf.moonrise.libs.org.yaml.snakeyaml'
|
relocate 'org.yaml.snakeyaml', 'ca.spottedleaf.moonrise.libs.org.yaml.snakeyaml'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,14 +8,15 @@ loader_version=0.16.7
|
|||||||
supported_minecraft_versions=1.21.3
|
supported_minecraft_versions=1.21.3
|
||||||
neoforge_version=21.3.31-beta
|
neoforge_version=21.3.31-beta
|
||||||
fabric_api_version=0.107.0+1.21.3
|
fabric_api_version=0.107.0+1.21.3
|
||||||
snakeyaml_version=2.2
|
snakeyaml_version=2.3
|
||||||
concurrentutil_version=0.0.2-SNAPSHOT
|
concurrentutil_version=0.0.2-SNAPSHOT
|
||||||
|
yamlconfig_version=1.0.2-SNAPSHOT
|
||||||
cloth_version=16.0.141
|
cloth_version=16.0.141
|
||||||
modmenu_version=12.0.0-beta.1
|
modmenu_version=12.0.0-beta.1
|
||||||
# version ids from modrinth
|
# version ids from modrinth
|
||||||
fabric_lithium_version=QhCwdt4l
|
fabric_lithium_version=QhCwdt4l
|
||||||
neo_lithium_version=wDD955sb
|
neo_lithium_version=wDD955sb
|
||||||
# Mod Properties
|
# Mod Properties
|
||||||
mod_version=0.2.0-beta.4
|
mod_version=0.2.0-beta.5
|
||||||
maven_group=ca.spottedleaf.moonrise
|
maven_group=ca.spottedleaf.moonrise
|
||||||
archives_base_name=moonrise
|
archives_base_name=moonrise
|
||||||
|
|||||||
@@ -2,5 +2,11 @@
|
|||||||
set -eou pipefail
|
set -eou pipefail
|
||||||
|
|
||||||
git submodule update --init --recursive
|
git submodule update --init --recursive
|
||||||
|
|
||||||
cd ConcurrentUtil
|
cd ConcurrentUtil
|
||||||
mvn install
|
mvn install
|
||||||
|
|
||||||
|
cd ..
|
||||||
|
|
||||||
|
cd YamlConfig
|
||||||
|
mvn install
|
||||||
@@ -22,6 +22,7 @@ dependencies {
|
|||||||
neoForge "net.neoforged:neoforge:${rootProject.neoforge_version}"
|
neoForge "net.neoforged:neoforge:${rootProject.neoforge_version}"
|
||||||
|
|
||||||
shadow("ca.spottedleaf:concurrentutil:${rootProject.concurrentutil_version}")
|
shadow("ca.spottedleaf:concurrentutil:${rootProject.concurrentutil_version}")
|
||||||
|
shadow("ca.spottedleaf:yamlconfig:${rootProject.yamlconfig_version}")
|
||||||
shadow("org.yaml:snakeyaml:${rootProject.snakeyaml_version}")
|
shadow("org.yaml:snakeyaml:${rootProject.snakeyaml_version}")
|
||||||
forgeExtra("org.yaml:snakeyaml:${rootProject.snakeyaml_version}")
|
forgeExtra("org.yaml:snakeyaml:${rootProject.snakeyaml_version}")
|
||||||
|
|
||||||
@@ -42,6 +43,7 @@ shadowJar {
|
|||||||
destinationDirectory = layout.buildDirectory.dir("libs")
|
destinationDirectory = layout.buildDirectory.dir("libs")
|
||||||
configurations = [project.configurations.shadow]
|
configurations = [project.configurations.shadow]
|
||||||
relocate 'ca.spottedleaf.concurrentutil', 'ca.spottedleaf.moonrise.libs.ca.spottedleaf.concurrentutil'
|
relocate 'ca.spottedleaf.concurrentutil', 'ca.spottedleaf.moonrise.libs.ca.spottedleaf.concurrentutil'
|
||||||
|
relocate 'ca.spottedleaf.yamlconfig', 'ca.spottedleaf.moonrise.libs.ca.spottedleaf.yamlconfig'
|
||||||
relocate 'org.yaml.snakeyaml', 'ca.spottedleaf.moonrise.libs.org.yaml.snakeyaml'
|
relocate 'org.yaml.snakeyaml', 'ca.spottedleaf.moonrise.libs.org.yaml.snakeyaml'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
package ca.spottedleaf.moonrise.common.config;
|
|
||||||
|
|
||||||
public interface InitialiseHook {
|
|
||||||
|
|
||||||
public void initialise();
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
package ca.spottedleaf.moonrise.common.config.adapter;
|
|
||||||
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
|
|
||||||
public abstract class TypeAdapter<T, S> {
|
|
||||||
|
|
||||||
public abstract T deserialize(final TypeAdapterRegistry registry, final Object input, final Type type);
|
|
||||||
|
|
||||||
public abstract S serialize(final TypeAdapterRegistry registry, final T value, final Type type);
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,307 +0,0 @@
|
|||||||
package ca.spottedleaf.moonrise.common.config.adapter;
|
|
||||||
|
|
||||||
import ca.spottedleaf.moonrise.common.config.InitialiseHook;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.collection.CollectionTypeAdapter;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.collection.ListTypeAdapter;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.collection.SortedMapTypeAdapter;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.primitive.BooleanTypeAdapter;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.primitive.ByteTypeAdapter;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.primitive.DoubleTypeAdapter;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.primitive.FloatTypeAdapter;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.primitive.IntegerTypeAdapter;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.primitive.LongTypeAdapter;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.primitive.ShortTypeAdapter;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.primitive.StringTypeAdapter;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.type.BigDecimalTypeAdapter;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.type.BigIntegerTypeAdapter;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.type.DurationTypeAdapter;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.annotation.Adaptable;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.annotation.Serializable;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.type.Duration;
|
|
||||||
import java.lang.annotation.Annotation;
|
|
||||||
import java.lang.reflect.Constructor;
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.lang.reflect.ParameterizedType;
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.math.BigInteger;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public final class TypeAdapterRegistry {
|
|
||||||
|
|
||||||
private final Map<Class<?>, TypeAdapter<?, ?>> adapters = new HashMap<>();
|
|
||||||
{
|
|
||||||
this.adapters.put(boolean.class, BooleanTypeAdapter.INSTANCE);
|
|
||||||
this.adapters.put(byte.class, ByteTypeAdapter.INSTANCE);
|
|
||||||
this.adapters.put(short.class, ShortTypeAdapter.INSTANCE);
|
|
||||||
this.adapters.put(int.class, IntegerTypeAdapter.INSTANCE);
|
|
||||||
this.adapters.put(long.class, LongTypeAdapter.INSTANCE);
|
|
||||||
this.adapters.put(float.class, FloatTypeAdapter.INSTANCE);
|
|
||||||
this.adapters.put(double.class, DoubleTypeAdapter.INSTANCE);
|
|
||||||
|
|
||||||
this.adapters.put(Boolean.class, BooleanTypeAdapter.INSTANCE);
|
|
||||||
this.adapters.put(Byte.class, ByteTypeAdapter.INSTANCE);
|
|
||||||
this.adapters.put(Short.class, ShortTypeAdapter.INSTANCE);
|
|
||||||
this.adapters.put(Integer.class, IntegerTypeAdapter.INSTANCE);
|
|
||||||
this.adapters.put(Long.class, LongTypeAdapter.INSTANCE);
|
|
||||||
this.adapters.put(Float.class, FloatTypeAdapter.INSTANCE);
|
|
||||||
this.adapters.put(Double.class, DoubleTypeAdapter.INSTANCE);
|
|
||||||
|
|
||||||
this.adapters.put(String.class, StringTypeAdapter.INSTANCE);
|
|
||||||
|
|
||||||
this.adapters.put(Collection.class, CollectionTypeAdapter.INSTANCE);
|
|
||||||
this.adapters.put(List.class, ListTypeAdapter.INSTANCE);
|
|
||||||
this.adapters.put(Map.class, SortedMapTypeAdapter.SORTED_CASE_INSENSITIVE);
|
|
||||||
this.adapters.put(LinkedHashMap.class, SortedMapTypeAdapter.SORTED_CASE_INSENSITIVE);
|
|
||||||
|
|
||||||
this.adapters.put(BigInteger.class, BigIntegerTypeAdapter.INSTANCE);
|
|
||||||
this.adapters.put(BigDecimal.class, BigDecimalTypeAdapter.INSTANCE);
|
|
||||||
this.adapters.put(Duration.class, DurationTypeAdapter.INSTANCE);
|
|
||||||
}
|
|
||||||
|
|
||||||
public TypeAdapter<?, ?> putAdapter(final Class<?> clazz, final TypeAdapter<?, ?> adapter) {
|
|
||||||
return this.adapters.put(clazz, adapter);
|
|
||||||
}
|
|
||||||
|
|
||||||
public TypeAdapter<?, ?> getAdapter(final Class<?> clazz) {
|
|
||||||
return this.adapters.get(clazz);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object deserialize(final Object input, final Type type) {
|
|
||||||
TypeAdapter<?, ?> adapter = null;
|
|
||||||
if (type instanceof Class<?> clazz) {
|
|
||||||
adapter = this.adapters.get(clazz);
|
|
||||||
}
|
|
||||||
if (adapter == null && (type instanceof ParameterizedType parameterizedType)) {
|
|
||||||
adapter = this.adapters.get((Class<?>)parameterizedType.getRawType());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (adapter == null) {
|
|
||||||
throw new IllegalArgumentException("No adapter for " + input.getClass() + " with type " + type);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ((TypeAdapter)adapter).deserialize(this, input, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object serialize(final Object input, final Type type) {
|
|
||||||
TypeAdapter<?, ?> adapter = null;
|
|
||||||
if (type instanceof Class<?> clazz) {
|
|
||||||
adapter = this.adapters.get(clazz);
|
|
||||||
}
|
|
||||||
if (adapter == null && (type instanceof ParameterizedType parameterizedType)) {
|
|
||||||
adapter = this.adapters.get((Class<?>)parameterizedType.getRawType());
|
|
||||||
}
|
|
||||||
if (adapter == null) {
|
|
||||||
adapter = this.adapters.get(input.getClass());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (adapter == null) {
|
|
||||||
throw new IllegalArgumentException("No adapter for " + input.getClass() + " with type " + type);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ((TypeAdapter)adapter).serialize(this, input, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
public <T> TypeAdapter<T, Map<Object, Object>> makeAdapter(final Class<? extends T> clazz) throws Exception {
|
|
||||||
final TypeAdapter<T, Map<Object, Object>> ret = new AutoTypeAdapter<>(this, clazz);
|
|
||||||
|
|
||||||
this.putAdapter(clazz, ret);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
public <T> void callInitialisers(final T object) {
|
|
||||||
if (object == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final TypeAdapter<?, ?> adapter = this.getAdapter(object.getClass());
|
|
||||||
|
|
||||||
if (!(adapter instanceof AutoTypeAdapter<?> autoTypeAdapter)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
((AutoTypeAdapter<T>)autoTypeAdapter).callInitialisers(object);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final class AutoTypeAdapter<T> extends TypeAdapter<T, Map<Object, Object>> {
|
|
||||||
|
|
||||||
private final TypeAdapterRegistry registry;
|
|
||||||
private final Constructor<? extends T> constructor;
|
|
||||||
private final SerializableField[] fields;
|
|
||||||
|
|
||||||
public AutoTypeAdapter(final TypeAdapterRegistry registry, final Class<? extends T> clazz) throws Exception {
|
|
||||||
this.registry = registry;
|
|
||||||
this.constructor = clazz.getConstructor();
|
|
||||||
this.fields = findSerializableFields(registry, clazz);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static TypeAdapter<?, ?> findOrMakeAdapter(final TypeAdapterRegistry registry, final Class<?> clazz) throws Exception {
|
|
||||||
final TypeAdapter<?, ?> ret = registry.getAdapter(clazz);
|
|
||||||
if (ret != null) {
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (final Annotation annotation : clazz.getAnnotations()) {
|
|
||||||
if (annotation instanceof Adaptable adaptable) {
|
|
||||||
return registry.makeAdapter(clazz);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new IllegalArgumentException("No type adapter for " + clazz + " (Forgot @Adaptable?)");
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String makeSerializedKey(final String input) {
|
|
||||||
final StringBuilder ret = new StringBuilder();
|
|
||||||
|
|
||||||
for (final char c : input.toCharArray()) {
|
|
||||||
if (!Character.isUpperCase(c)) {
|
|
||||||
ret.append(c);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
ret.append('-');
|
|
||||||
ret.append(Character.toLowerCase(c));
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static record SerializableField(
|
|
||||||
Field field,
|
|
||||||
boolean required,
|
|
||||||
String comment,
|
|
||||||
TypeAdapter<?, ?> adapter,
|
|
||||||
boolean serialize,
|
|
||||||
String serializedKey
|
|
||||||
) {}
|
|
||||||
|
|
||||||
private static SerializableField[] findSerializableFields(final TypeAdapterRegistry registry, Class<?> clazz) throws Exception {
|
|
||||||
final List<SerializableField> ret = new ArrayList<>();
|
|
||||||
do {
|
|
||||||
for (final Field field : clazz.getDeclaredFields()) {
|
|
||||||
field.setAccessible(true);
|
|
||||||
|
|
||||||
for (final Annotation annotation : field.getAnnotations()) {
|
|
||||||
if (!(annotation instanceof Serializable serializable)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
final TypeAdapter<?, ?> adapter;
|
|
||||||
|
|
||||||
if (serializable.adapter() != TypeAdapter.class) {
|
|
||||||
adapter = serializable.adapter().getConstructor().newInstance();
|
|
||||||
} else {
|
|
||||||
adapter = findOrMakeAdapter(registry, field.getType());
|
|
||||||
}
|
|
||||||
|
|
||||||
String serializedKey = serializable.serializedKey();
|
|
||||||
if (serializedKey.isEmpty()) {
|
|
||||||
serializedKey = makeSerializedKey(field.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
ret.add(new SerializableField(
|
|
||||||
field, serializable.required(), serializable.comment(), adapter,
|
|
||||||
serializable.serialize(), serializedKey
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} while ((clazz = clazz.getSuperclass()) != Object.class);
|
|
||||||
|
|
||||||
ret.sort((final SerializableField c1, final SerializableField c2) -> {
|
|
||||||
return c1.serializedKey.compareTo(c2.serializedKey);
|
|
||||||
});
|
|
||||||
|
|
||||||
return ret.toArray(new SerializableField[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public T deserialize(final TypeAdapterRegistry registry, final Object input, final Type type) {
|
|
||||||
if (!(input instanceof Map<?,?> inputMap)) {
|
|
||||||
throw new IllegalArgumentException("Not a map type: " + input.getClass());
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
final T ret = this.constructor.newInstance();
|
|
||||||
|
|
||||||
for (final SerializableField field : this.fields) {
|
|
||||||
final Object fieldValue = inputMap.get(field.serializedKey);
|
|
||||||
|
|
||||||
if (fieldValue == null) {
|
|
||||||
if (field.required) {
|
|
||||||
throw new IllegalArgumentException("Missing required field '" + field.serializedKey + "' in " + this.constructor.getDeclaringClass());
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
field.field.set(ret, field.adapter.deserialize(registry, fieldValue, field.field.getGenericType()));
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
} catch (final Exception ex) {
|
|
||||||
throw new RuntimeException(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<Object, Object> serialize(final TypeAdapterRegistry registry, final T value, final Type type) {
|
|
||||||
final LinkedHashMap<Object, Object> ret = new LinkedHashMap<>();
|
|
||||||
|
|
||||||
for (final SerializableField field : this.fields) {
|
|
||||||
if (!field.serialize) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
final Object fieldValue;
|
|
||||||
try {
|
|
||||||
fieldValue = field.field.get(value);
|
|
||||||
} catch (final Exception ex) {
|
|
||||||
throw new RuntimeException(ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fieldValue != null) {
|
|
||||||
ret.put(
|
|
||||||
field.comment.isBlank() ? field.serializedKey : new CommentedData(field.comment, field.serializedKey),
|
|
||||||
((TypeAdapter)field.adapter).serialize(
|
|
||||||
registry, fieldValue, field.field.getGenericType()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void callInitialisers(final T value) {
|
|
||||||
for (final SerializableField field : this.fields) {
|
|
||||||
final Object fieldValue;
|
|
||||||
try {
|
|
||||||
fieldValue = field.field.get(value);
|
|
||||||
} catch (final Exception ex) {
|
|
||||||
throw new RuntimeException(ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fieldValue instanceof InitialiseHook initialiseHook) {
|
|
||||||
initialiseHook.initialise();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.registry.callInitialisers(fieldValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final class CommentedData {
|
|
||||||
|
|
||||||
public final String comment;
|
|
||||||
public final Object data;
|
|
||||||
|
|
||||||
public CommentedData(final String comment, final Object data) {
|
|
||||||
this.comment = comment;
|
|
||||||
this.data = data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
package ca.spottedleaf.moonrise.common.config.adapter.collection;
|
|
||||||
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapter;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapterRegistry;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.primitive.StringTypeAdapter;
|
|
||||||
import java.lang.reflect.ParameterizedType;
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public final class CollectionTypeAdapter extends TypeAdapter<Collection<Object>, List<Object>> {
|
|
||||||
|
|
||||||
public static final CollectionTypeAdapter INSTANCE = new CollectionTypeAdapter();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Collection<Object> deserialize(final TypeAdapterRegistry registry, final Object input, final Type type) {
|
|
||||||
if (!(type instanceof ParameterizedType parameterizedType)) {
|
|
||||||
throw new IllegalArgumentException("Collection field must specify generic type");
|
|
||||||
}
|
|
||||||
final Type elementType = parameterizedType.getActualTypeArguments()[0];
|
|
||||||
if (input instanceof Collection<?> collection) {
|
|
||||||
final List<Object> ret = new ArrayList<>(collection.size());
|
|
||||||
|
|
||||||
for (final Object v : collection) {
|
|
||||||
ret.add(registry.deserialize(v, elementType));
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
throw new IllegalArgumentException("Not a collection type: " + input.getClass());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<Object> serialize(final TypeAdapterRegistry registry, final Collection<Object> value, final Type type) {
|
|
||||||
final List<Object> ret = new ArrayList<>(value.size());
|
|
||||||
|
|
||||||
final Type elementType = type instanceof ParameterizedType parameterizedType ? parameterizedType.getActualTypeArguments()[0] : null;
|
|
||||||
|
|
||||||
for (final Object v : value) {
|
|
||||||
ret.add(registry.serialize(v, elementType == null ? v.getClass() : elementType));
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
package ca.spottedleaf.moonrise.common.config.adapter.collection;
|
|
||||||
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapter;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapterRegistry;
|
|
||||||
import java.lang.reflect.ParameterizedType;
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public final class ListTypeAdapter extends TypeAdapter<List<Object>, List<Object>> {
|
|
||||||
|
|
||||||
public static final ListTypeAdapter INSTANCE = new ListTypeAdapter();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<Object> deserialize(final TypeAdapterRegistry registry, final Object input, final Type type) {
|
|
||||||
if (!(type instanceof ParameterizedType parameterizedType)) {
|
|
||||||
throw new IllegalArgumentException("Collection field must specify generic type");
|
|
||||||
}
|
|
||||||
final Type elementType = parameterizedType.getActualTypeArguments()[0];
|
|
||||||
if (input instanceof Collection<?> collection) {
|
|
||||||
final List<Object> ret = new ArrayList<>(collection.size());
|
|
||||||
|
|
||||||
for (final Object v : collection) {
|
|
||||||
ret.add(registry.deserialize(v, elementType));
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
throw new IllegalArgumentException("Not a collection type: " + input.getClass());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<Object> serialize(final TypeAdapterRegistry registry, final List<Object> value, final Type type) {
|
|
||||||
final List<Object> ret = new ArrayList<>(value.size());
|
|
||||||
|
|
||||||
final Type elementType = type instanceof ParameterizedType parameterizedType ? parameterizedType.getActualTypeArguments()[0] : null;
|
|
||||||
|
|
||||||
for (final Object v : value) {
|
|
||||||
ret.add(registry.serialize(v, elementType));
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
package ca.spottedleaf.moonrise.common.config.adapter.collection;
|
|
||||||
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapter;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapterRegistry;
|
|
||||||
import java.lang.reflect.ParameterizedType;
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.TreeMap;
|
|
||||||
|
|
||||||
public final class SortedMapTypeAdapter extends TypeAdapter<Map<String, Object>, Map<String, Object>> {
|
|
||||||
|
|
||||||
public static final SortedMapTypeAdapter SORTED_CASE_INSENSITIVE = new SortedMapTypeAdapter(String.CASE_INSENSITIVE_ORDER);
|
|
||||||
public static final SortedMapTypeAdapter SORTED_CASE_SENSITIVE = new SortedMapTypeAdapter(null);
|
|
||||||
|
|
||||||
private final Comparator<String> keyComparator;
|
|
||||||
|
|
||||||
public SortedMapTypeAdapter(final Comparator<String> keyComparator) {
|
|
||||||
this.keyComparator = keyComparator;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<String, Object> deserialize(final TypeAdapterRegistry registry, final Object input, final Type type) {
|
|
||||||
if (!(type instanceof ParameterizedType parameterizedType)) {
|
|
||||||
throw new IllegalArgumentException("Collection field must specify generic type");
|
|
||||||
}
|
|
||||||
final Type valueType = parameterizedType.getActualTypeArguments()[1];
|
|
||||||
if (input instanceof Map<?,?> inputMap) {
|
|
||||||
final Map<String, Object> castedInput = (Map<String, Object>)inputMap;
|
|
||||||
|
|
||||||
final TreeMap<String, Object> ret = new TreeMap<>(this.keyComparator);
|
|
||||||
|
|
||||||
for (final Map.Entry<String, Object> entry : castedInput.entrySet()) {
|
|
||||||
ret.put(entry.getKey(), registry.deserialize(entry.getValue(), valueType));
|
|
||||||
}
|
|
||||||
|
|
||||||
// transform to linked so that get() is O(1)
|
|
||||||
return new LinkedHashMap<>(ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new IllegalArgumentException("Not a map type: " + input.getClass());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<String, Object> serialize(final TypeAdapterRegistry registry, final Map<String, Object> value, final Type type) {
|
|
||||||
final TreeMap<String, Object> ret = new TreeMap<>(this.keyComparator);
|
|
||||||
|
|
||||||
final Type valueType = type instanceof ParameterizedType parameterizedType ? parameterizedType.getActualTypeArguments()[1] : null;
|
|
||||||
|
|
||||||
for (final Map.Entry<String, Object> entry : value.entrySet()) {
|
|
||||||
ret.put(entry.getKey(), registry.serialize(entry.getValue(), valueType));
|
|
||||||
}
|
|
||||||
|
|
||||||
// transform to linked so that get() is O(1)
|
|
||||||
return new LinkedHashMap<>(ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
package ca.spottedleaf.moonrise.common.config.adapter.collection;
|
|
||||||
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapter;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapterRegistry;
|
|
||||||
import java.lang.reflect.ParameterizedType;
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public final class UnsortedMapTypeAdapter extends TypeAdapter<Map<String, Object>, Map<String, Object>> {
|
|
||||||
|
|
||||||
public static final UnsortedMapTypeAdapter INSTANCE = new UnsortedMapTypeAdapter();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<String, Object> deserialize(final TypeAdapterRegistry registry, final Object input, final Type type) {
|
|
||||||
if (!(type instanceof ParameterizedType parameterizedType)) {
|
|
||||||
throw new IllegalArgumentException("Collection field must specify generic type");
|
|
||||||
}
|
|
||||||
final Type valueType = parameterizedType.getActualTypeArguments()[1];
|
|
||||||
if (input instanceof Map<?,?> inputMap) {
|
|
||||||
final Map<String, Object> castedInput = (Map<String, Object>)inputMap;
|
|
||||||
|
|
||||||
final LinkedHashMap<String, Object> ret = new LinkedHashMap<>();
|
|
||||||
|
|
||||||
for (final Map.Entry<String, Object> entry : castedInput.entrySet()) {
|
|
||||||
ret.put(entry.getKey(), registry.deserialize(entry.getValue(), valueType));
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new IllegalArgumentException("Not a map type: " + input.getClass());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<String, Object> serialize(final TypeAdapterRegistry registry, final Map<String, Object> value, final Type type) {
|
|
||||||
final LinkedHashMap<String, Object> ret = new LinkedHashMap<>();
|
|
||||||
|
|
||||||
final Type valueType = type instanceof ParameterizedType parameterizedType ? parameterizedType.getActualTypeArguments()[1] : null;
|
|
||||||
|
|
||||||
for (final Map.Entry<String, Object> entry : value.entrySet()) {
|
|
||||||
ret.put(entry.getKey(), registry.serialize(entry.getValue(), valueType));
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
package ca.spottedleaf.moonrise.common.config.adapter.primitive;
|
|
||||||
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapter;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapterRegistry;
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
|
|
||||||
public final class BooleanTypeAdapter extends TypeAdapter<Boolean, Boolean> {
|
|
||||||
|
|
||||||
public static final BooleanTypeAdapter INSTANCE = new BooleanTypeAdapter();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Boolean deserialize(final TypeAdapterRegistry registry, final Object input, final Type type) {
|
|
||||||
if (input instanceof Boolean ret) {
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
if (input instanceof String str) {
|
|
||||||
if (str.equalsIgnoreCase("false")) {
|
|
||||||
return Boolean.FALSE;
|
|
||||||
}
|
|
||||||
if (str.equalsIgnoreCase("true")) {
|
|
||||||
return Boolean.TRUE;
|
|
||||||
}
|
|
||||||
throw new IllegalArgumentException("Not a boolean: " + str);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new IllegalArgumentException("Not a boolean type: " + input.getClass());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Boolean serialize(final TypeAdapterRegistry registry, final Boolean value, final Type type) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
package ca.spottedleaf.moonrise.common.config.adapter.primitive;
|
|
||||||
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapter;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapterRegistry;
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
import java.math.BigInteger;
|
|
||||||
|
|
||||||
public final class ByteTypeAdapter extends TypeAdapter<Byte, Byte> {
|
|
||||||
|
|
||||||
public static final ByteTypeAdapter INSTANCE = new ByteTypeAdapter();
|
|
||||||
|
|
||||||
private static Byte cast(final Object original, final long value) {
|
|
||||||
if (value < (long)Byte.MIN_VALUE || value > (long)Byte.MAX_VALUE) {
|
|
||||||
throw new IllegalArgumentException("Byte value is out of range: " + original.toString());
|
|
||||||
}
|
|
||||||
return Byte.valueOf((byte)value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Byte deserialize(final TypeAdapterRegistry registry, final Object input, final Type type) {
|
|
||||||
if (input instanceof Number number) {
|
|
||||||
// note: silently discard floating point significand
|
|
||||||
return cast(input, number instanceof BigInteger bigInteger ? bigInteger.longValueExact() : number.longValue());
|
|
||||||
}
|
|
||||||
if (input instanceof String string) {
|
|
||||||
return cast(input, (long)Double.parseDouble(string));
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new IllegalArgumentException("Not a byte type: " + input.getClass());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Byte serialize(final TypeAdapterRegistry registry, final Byte value, final Type type) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
package ca.spottedleaf.moonrise.common.config.adapter.primitive;
|
|
||||||
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapter;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapterRegistry;
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
|
|
||||||
public final class DoubleTypeAdapter extends TypeAdapter<Double, Double> {
|
|
||||||
|
|
||||||
public static final DoubleTypeAdapter INSTANCE = new DoubleTypeAdapter();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Double deserialize(final TypeAdapterRegistry registry, final Object input, final Type type) {
|
|
||||||
if (input instanceof Number number) {
|
|
||||||
return Double.valueOf(number.doubleValue());
|
|
||||||
}
|
|
||||||
if (input instanceof String string) {
|
|
||||||
return Double.valueOf(Double.parseDouble(string));
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new IllegalArgumentException("Not a byte type: " + input.getClass());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Double serialize(final TypeAdapterRegistry registry, final Double value, final Type type) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
package ca.spottedleaf.moonrise.common.config.adapter.primitive;
|
|
||||||
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapter;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapterRegistry;
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
|
|
||||||
public final class FloatTypeAdapter extends TypeAdapter<Float, Float> {
|
|
||||||
|
|
||||||
public static final FloatTypeAdapter INSTANCE = new FloatTypeAdapter();
|
|
||||||
|
|
||||||
private static Float cast(final Object original, final double value) {
|
|
||||||
if (value < -(double)Float.MAX_VALUE || value > (double)Float.MAX_VALUE) {
|
|
||||||
throw new IllegalArgumentException("Byte value is out of range: " + original.toString());
|
|
||||||
}
|
|
||||||
// note: silently ignore precision loss
|
|
||||||
return Float.valueOf((float)value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Float deserialize(final TypeAdapterRegistry registry, final Object input, final Type type) {
|
|
||||||
if (input instanceof Number number) {
|
|
||||||
return cast(input, number.doubleValue());
|
|
||||||
}
|
|
||||||
if (input instanceof String string) {
|
|
||||||
return cast(input, Double.parseDouble(string));
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new IllegalArgumentException("Not a byte type: " + input.getClass());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Float serialize(final TypeAdapterRegistry registry, final Float value, final Type type) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
package ca.spottedleaf.moonrise.common.config.adapter.primitive;
|
|
||||||
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapter;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapterRegistry;
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
import java.math.BigInteger;
|
|
||||||
|
|
||||||
public final class IntegerTypeAdapter extends TypeAdapter<Integer, Integer> {
|
|
||||||
|
|
||||||
public static final IntegerTypeAdapter INSTANCE = new IntegerTypeAdapter();
|
|
||||||
|
|
||||||
private static Integer cast(final Object original, final long value) {
|
|
||||||
if (value < (long)Integer.MIN_VALUE || value > (long)Integer.MAX_VALUE) {
|
|
||||||
throw new IllegalArgumentException("Integer value is out of range: " + original.toString());
|
|
||||||
}
|
|
||||||
return Integer.valueOf((int)value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Integer deserialize(final TypeAdapterRegistry registry, final Object input, final Type type) {
|
|
||||||
if (input instanceof Number number) {
|
|
||||||
// note: silently discard floating point significand
|
|
||||||
return cast(input, number instanceof BigInteger bigInteger ? bigInteger.longValueExact() : number.longValue());
|
|
||||||
}
|
|
||||||
if (input instanceof String string) {
|
|
||||||
return cast(input, (long)Double.parseDouble(string));
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new IllegalArgumentException("Not an integer type: " + input.getClass());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Integer serialize(final TypeAdapterRegistry registry, final Integer value, final Type type) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
package ca.spottedleaf.moonrise.common.config.adapter.primitive;
|
|
||||||
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapter;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapterRegistry;
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
import java.math.BigInteger;
|
|
||||||
|
|
||||||
public final class LongTypeAdapter extends TypeAdapter<Long, Long> {
|
|
||||||
|
|
||||||
public static final LongTypeAdapter INSTANCE = new LongTypeAdapter();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Long deserialize(final TypeAdapterRegistry registry, final Object input, final Type type) {
|
|
||||||
if (input instanceof Number number) {
|
|
||||||
// note: silently discard floating point significand
|
|
||||||
return number instanceof BigInteger bigInteger ? bigInteger.longValueExact() : number.longValue();
|
|
||||||
}
|
|
||||||
if (input instanceof String string) {
|
|
||||||
try {
|
|
||||||
return Long.valueOf(Long.parseLong(string));
|
|
||||||
} catch (final NumberFormatException ex) {
|
|
||||||
return Long.valueOf((long)Double.parseDouble(string));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new IllegalArgumentException("Not a long type: " + input.getClass());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Long serialize(final TypeAdapterRegistry registry, final Long value, final Type type) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
package ca.spottedleaf.moonrise.common.config.adapter.primitive;
|
|
||||||
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapter;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapterRegistry;
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
import java.math.BigInteger;
|
|
||||||
|
|
||||||
public final class ShortTypeAdapter extends TypeAdapter<Short, Short> {
|
|
||||||
|
|
||||||
public static final ShortTypeAdapter INSTANCE = new ShortTypeAdapter();
|
|
||||||
|
|
||||||
private static Short cast(final Object original, final long value) {
|
|
||||||
if (value < (long)Short.MIN_VALUE || value > (long)Short.MAX_VALUE) {
|
|
||||||
throw new IllegalArgumentException("Short value is out of range: " + original.toString());
|
|
||||||
}
|
|
||||||
return Short.valueOf((short)value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Short deserialize(final TypeAdapterRegistry registry, final Object input, final Type type) {
|
|
||||||
if (input instanceof Number number) {
|
|
||||||
// note: silently discard floating point significand
|
|
||||||
return cast(input, number instanceof BigInteger bigInteger ? bigInteger.longValueExact() : number.longValue());
|
|
||||||
}
|
|
||||||
if (input instanceof String string) {
|
|
||||||
return cast(input, (long)Double.parseDouble(string));
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new IllegalArgumentException("Not a short type: " + input.getClass());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Short serialize(final TypeAdapterRegistry registry, final Short value, final Type type) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
package ca.spottedleaf.moonrise.common.config.adapter.primitive;
|
|
||||||
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapter;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapterRegistry;
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
|
|
||||||
public final class StringTypeAdapter extends TypeAdapter<String, String> {
|
|
||||||
|
|
||||||
public static final StringTypeAdapter INSTANCE = new StringTypeAdapter();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String deserialize(final TypeAdapterRegistry registry, final Object input, final Type type) {
|
|
||||||
if (input instanceof Boolean bool) {
|
|
||||||
return String.valueOf(bool.booleanValue());
|
|
||||||
}
|
|
||||||
if (input instanceof Number number) {
|
|
||||||
return number.toString();
|
|
||||||
}
|
|
||||||
if (input instanceof String string) {
|
|
||||||
return string;
|
|
||||||
}
|
|
||||||
throw new IllegalArgumentException("Not a string type: " + input.getClass());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String serialize(final TypeAdapterRegistry registry, final String value, final Type type) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
package ca.spottedleaf.moonrise.common.config.adapter.type;
|
|
||||||
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapter;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapterRegistry;
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.math.BigInteger;
|
|
||||||
|
|
||||||
public final class BigDecimalTypeAdapter extends TypeAdapter<BigDecimal, String> {
|
|
||||||
|
|
||||||
public static final BigDecimalTypeAdapter INSTANCE = new BigDecimalTypeAdapter();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BigDecimal deserialize(final TypeAdapterRegistry registry, final Object input, final Type type) {
|
|
||||||
if (input instanceof Number number) {
|
|
||||||
// safest to catch all number impls is to use toString
|
|
||||||
return new BigDecimal(number.toString());
|
|
||||||
}
|
|
||||||
if (input instanceof String string) {
|
|
||||||
return new BigDecimal(string);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new IllegalArgumentException("Not an BigDecimal type: " + input.getClass());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String serialize(final TypeAdapterRegistry registry, final BigDecimal value, final Type type) {
|
|
||||||
return value.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
package ca.spottedleaf.moonrise.common.config.adapter.type;
|
|
||||||
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapter;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapterRegistry;
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.math.BigInteger;
|
|
||||||
|
|
||||||
public final class BigIntegerTypeAdapter extends TypeAdapter<BigInteger, String> {
|
|
||||||
|
|
||||||
public static final BigIntegerTypeAdapter INSTANCE = new BigIntegerTypeAdapter();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BigInteger deserialize(final TypeAdapterRegistry registry, final Object input, final Type type) {
|
|
||||||
if (input instanceof Number number) {
|
|
||||||
if (number instanceof BigInteger bigInteger) {
|
|
||||||
return bigInteger;
|
|
||||||
}
|
|
||||||
// note: silently discard floating point significand
|
|
||||||
if (number instanceof BigDecimal bigDecimal) {
|
|
||||||
return bigDecimal.toBigInteger();
|
|
||||||
}
|
|
||||||
|
|
||||||
return BigInteger.valueOf(number.longValue());
|
|
||||||
}
|
|
||||||
if (input instanceof String string) {
|
|
||||||
return new BigDecimal(string).toBigInteger();
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new IllegalArgumentException("Not an BigInteger type: " + input.getClass());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String serialize(final TypeAdapterRegistry registry, final BigInteger value, final Type type) {
|
|
||||||
return value.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
package ca.spottedleaf.moonrise.common.config.adapter.type;
|
|
||||||
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapter;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapterRegistry;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.type.Duration;
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
|
|
||||||
public final class DurationTypeAdapter extends TypeAdapter<Duration, String> {
|
|
||||||
|
|
||||||
public static final DurationTypeAdapter INSTANCE = new DurationTypeAdapter();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Duration deserialize(final TypeAdapterRegistry registry, final Object input, final Type type) {
|
|
||||||
if (!(input instanceof String string)) {
|
|
||||||
throw new IllegalArgumentException("Not a string: " + input.getClass());
|
|
||||||
}
|
|
||||||
return Duration.parse(string);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String serialize(final TypeAdapterRegistry registry, final Duration value, final Type type) {
|
|
||||||
return value.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
package ca.spottedleaf.moonrise.common.config.annotation;
|
|
||||||
|
|
||||||
import java.lang.annotation.ElementType;
|
|
||||||
import java.lang.annotation.Retention;
|
|
||||||
import java.lang.annotation.RetentionPolicy;
|
|
||||||
import java.lang.annotation.Target;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Annotation used on a class to indicate that its type adapter may automatically be generated. The class must have
|
|
||||||
* a public no-args constructor.
|
|
||||||
*/
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
@Target(ElementType.TYPE)
|
|
||||||
public @interface Adaptable {
|
|
||||||
}
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
package ca.spottedleaf.moonrise.common.config.annotation;
|
|
||||||
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapter;
|
|
||||||
import java.lang.annotation.ElementType;
|
|
||||||
import java.lang.annotation.Retention;
|
|
||||||
import java.lang.annotation.RetentionPolicy;
|
|
||||||
import java.lang.annotation.Target;
|
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Annotation indicating that a field should be deserialized or serialized from the config.
|
|
||||||
* By default, this annotation is not assumed.
|
|
||||||
*/
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
@Target(ElementType.FIELD)
|
|
||||||
public @interface Serializable {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Indicates whether this field is required to be present in the config. If the field is not present,
|
|
||||||
* and {@code required = true}, then an exception will be thrown during deserialization. If {@code required = false}
|
|
||||||
* and the field is not present, then the field value will remain unmodified.
|
|
||||||
*/
|
|
||||||
public boolean required() default false;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The comment to apply before the element when serializing.
|
|
||||||
*/
|
|
||||||
public String comment() default "";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adapter override class. The class must have a public no-args constructor.
|
|
||||||
*/
|
|
||||||
public Class<? extends TypeAdapter> adapter() default TypeAdapter.class;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether to serialize the value to the config.
|
|
||||||
*/
|
|
||||||
public boolean serialize() default true;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* When not empty, this value overrides the auto generated serialized key in the config.
|
|
||||||
*/
|
|
||||||
public String serializedKey() default "";
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,178 +0,0 @@
|
|||||||
package ca.spottedleaf.moonrise.common.config.config;
|
|
||||||
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapterRegistry;
|
|
||||||
import org.yaml.snakeyaml.DumperOptions;
|
|
||||||
import org.yaml.snakeyaml.LoaderOptions;
|
|
||||||
import org.yaml.snakeyaml.Yaml;
|
|
||||||
import org.yaml.snakeyaml.comments.CommentLine;
|
|
||||||
import org.yaml.snakeyaml.comments.CommentType;
|
|
||||||
import org.yaml.snakeyaml.constructor.Constructor;
|
|
||||||
import org.yaml.snakeyaml.nodes.Node;
|
|
||||||
import org.yaml.snakeyaml.representer.Represent;
|
|
||||||
import org.yaml.snakeyaml.representer.Representer;
|
|
||||||
import java.io.BufferedInputStream;
|
|
||||||
import java.io.BufferedOutputStream;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.io.StringReader;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.nio.file.AtomicMoveNotSupportedException;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.StandardCopyOption;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.TreeMap;
|
|
||||||
|
|
||||||
public final class YamlConfig<T> {
|
|
||||||
|
|
||||||
public final TypeAdapterRegistry typeAdapters;
|
|
||||||
|
|
||||||
private final Class<? extends T> clazz;
|
|
||||||
|
|
||||||
public volatile T config;
|
|
||||||
|
|
||||||
private final Yaml yaml;
|
|
||||||
private final LoaderOptions loaderOptions;
|
|
||||||
private final DumperOptions dumperOptions;
|
|
||||||
|
|
||||||
public YamlConfig(final Class<? extends T> clazz, final T dfl) throws Exception {
|
|
||||||
this(clazz, dfl, new TypeAdapterRegistry());
|
|
||||||
}
|
|
||||||
|
|
||||||
public YamlConfig(final Class<? extends T> clazz, final T dfl, final TypeAdapterRegistry registry) throws Exception {
|
|
||||||
this.clazz = clazz;
|
|
||||||
this.config = dfl;
|
|
||||||
this.typeAdapters = registry;
|
|
||||||
this.typeAdapters.makeAdapter(clazz);
|
|
||||||
|
|
||||||
final LoaderOptions loaderOptions = new LoaderOptions();
|
|
||||||
loaderOptions.setProcessComments(true);
|
|
||||||
|
|
||||||
final DumperOptions dumperOptions = new DumperOptions();
|
|
||||||
dumperOptions.setProcessComments(true);
|
|
||||||
dumperOptions.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
|
|
||||||
|
|
||||||
this.loaderOptions = loaderOptions;
|
|
||||||
this.dumperOptions = dumperOptions;
|
|
||||||
this.yaml = new Yaml(new YamlConstructor(loaderOptions), new YamlRepresenter(dumperOptions), dumperOptions, loaderOptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void load(final File file) throws IOException {
|
|
||||||
try (final InputStream is = new BufferedInputStream(new FileInputStream(file))) {
|
|
||||||
this.load(is);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void load(final InputStream is) throws IOException {
|
|
||||||
final Object serialized = this.yaml.load(new InputStreamReader(is, StandardCharsets.UTF_8));
|
|
||||||
|
|
||||||
this.config = (T)this.typeAdapters.deserialize(serialized, this.clazz);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void save(final File file) throws IOException {
|
|
||||||
this.save(file, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void save(final File file, final String header) throws IOException {
|
|
||||||
if (file.isDirectory()) {
|
|
||||||
throw new IOException("File is a directory");
|
|
||||||
}
|
|
||||||
|
|
||||||
final File parent = file.getParentFile();
|
|
||||||
if (parent != null) {
|
|
||||||
parent.mkdirs();
|
|
||||||
}
|
|
||||||
|
|
||||||
final File tmp = new File(parent, file.getName() + ".tmp");
|
|
||||||
tmp.delete();
|
|
||||||
tmp.createNewFile();
|
|
||||||
try {
|
|
||||||
try (final OutputStream os = new BufferedOutputStream(new FileOutputStream(tmp))) {
|
|
||||||
this.save(os, header);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
Files.move(tmp.toPath(), file.toPath(), StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.ATOMIC_MOVE);
|
|
||||||
} catch (final AtomicMoveNotSupportedException ex) {
|
|
||||||
Files.move(tmp.toPath(), file.toPath(), StandardCopyOption.REPLACE_EXISTING);
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
tmp.delete();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void save(final OutputStream os) throws IOException {
|
|
||||||
os.write(this.saveToString().getBytes(StandardCharsets.UTF_8));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void save(final OutputStream os, final String header) throws IOException {
|
|
||||||
os.write(this.saveToString(header).getBytes(StandardCharsets.UTF_8));
|
|
||||||
}
|
|
||||||
|
|
||||||
public String saveToString() {
|
|
||||||
return this.yaml.dump(this.typeAdapters.serialize(this.config, this.clazz));
|
|
||||||
}
|
|
||||||
|
|
||||||
public String saveToString(final String header) {
|
|
||||||
if (header.isBlank()) {
|
|
||||||
return this.saveToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
final StringBuilder ret = new StringBuilder();
|
|
||||||
final String lineBreak = this.dumperOptions.getLineBreak().getString();
|
|
||||||
|
|
||||||
for (final String line : header.split("\n")) {
|
|
||||||
ret.append("# ").append(line.trim()).append(lineBreak);
|
|
||||||
}
|
|
||||||
|
|
||||||
ret.append(lineBreak);
|
|
||||||
|
|
||||||
return ret.append(this.saveToString()).toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void callInitialisers() {
|
|
||||||
this.typeAdapters.callInitialisers(this.config);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final class YamlConstructor extends Constructor {
|
|
||||||
|
|
||||||
public YamlConstructor(final LoaderOptions loadingConfig) {
|
|
||||||
super(loadingConfig);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final class YamlRepresenter extends Representer {
|
|
||||||
|
|
||||||
public YamlRepresenter(final DumperOptions options) {
|
|
||||||
super(options);
|
|
||||||
|
|
||||||
this.representers.put(TypeAdapterRegistry.CommentedData.class, new CommentedDataRepresenter());
|
|
||||||
}
|
|
||||||
|
|
||||||
private final class CommentedDataRepresenter implements Represent {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Node representData(final Object data0) {
|
|
||||||
final TypeAdapterRegistry.CommentedData commentedData = (TypeAdapterRegistry.CommentedData)data0;
|
|
||||||
|
|
||||||
final Node node = YamlRepresenter.this.representData(commentedData.data);
|
|
||||||
|
|
||||||
final List<CommentLine> comments = new ArrayList<>();
|
|
||||||
|
|
||||||
for (final String line : commentedData.comment.split("\n")) {
|
|
||||||
comments.add(new CommentLine(null, null, " ".concat(line.trim()), CommentType.BLOCK));
|
|
||||||
}
|
|
||||||
|
|
||||||
node.setBlockComments(comments);
|
|
||||||
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
package ca.spottedleaf.moonrise.common.config.moonrise;
|
package ca.spottedleaf.moonrise.common.config.moonrise;
|
||||||
|
|
||||||
import ca.spottedleaf.moonrise.common.config.InitialiseHook;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.annotation.Adaptable;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.ui.ClothConfig;
|
import ca.spottedleaf.moonrise.common.config.ui.ClothConfig;
|
||||||
import ca.spottedleaf.moonrise.common.config.annotation.Serializable;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.type.Duration;
|
|
||||||
import ca.spottedleaf.moonrise.common.util.MoonriseCommon;
|
import ca.spottedleaf.moonrise.common.util.MoonriseCommon;
|
||||||
import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkTaskScheduler;
|
import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkTaskScheduler;
|
||||||
|
import ca.spottedleaf.yamlconfig.InitialiseHook;
|
||||||
|
import ca.spottedleaf.yamlconfig.annotation.Adaptable;
|
||||||
|
import ca.spottedleaf.yamlconfig.annotation.Serializable;
|
||||||
|
import ca.spottedleaf.yamlconfig.type.Duration;
|
||||||
|
|
||||||
@Adaptable
|
@Adaptable
|
||||||
public final class MoonriseConfig {
|
public final class MoonriseConfig {
|
||||||
@@ -251,4 +251,21 @@ public final class MoonriseConfig {
|
|||||||
)
|
)
|
||||||
public boolean fixMC159283 = false;
|
public boolean fixMC159283 = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
public Misc misc = new Misc();
|
||||||
|
|
||||||
|
@Adaptable
|
||||||
|
public static final class Misc {
|
||||||
|
|
||||||
|
@Serializable(
|
||||||
|
serializedKey = "immediately-close-loading-screen",
|
||||||
|
comment = """
|
||||||
|
Whether the loading screen should be closed immediately when joining servers/SP worlds.
|
||||||
|
This will let you in game faster, but may result in getting in game before enough chunks are
|
||||||
|
loaded for rendering.
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
public boolean immediatelyCloseLoadingScreen = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,38 +0,0 @@
|
|||||||
package ca.spottedleaf.moonrise.common.config.moonrise.adapter;
|
|
||||||
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapter;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapterRegistry;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.moonrise.type.DefaultedValue;
|
|
||||||
import java.lang.reflect.ParameterizedType;
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
|
|
||||||
public final class DefaultedTypeAdapter extends TypeAdapter<DefaultedValue<?>, Object> {
|
|
||||||
|
|
||||||
private static final String DEFAULT_STRING = "default";
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DefaultedValue<?> deserialize(final TypeAdapterRegistry registry, final Object input, final Type type) {
|
|
||||||
if (input instanceof String string && string.equalsIgnoreCase(DEFAULT_STRING)) {
|
|
||||||
return new DefaultedValue<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(type instanceof ParameterizedType parameterizedType)) {
|
|
||||||
throw new IllegalArgumentException("DefaultedValue field must specify generic type");
|
|
||||||
}
|
|
||||||
final Type valueType = parameterizedType.getActualTypeArguments()[0];
|
|
||||||
|
|
||||||
return new DefaultedValue<>(registry.deserialize(input, valueType));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object serialize(final TypeAdapterRegistry registry, final DefaultedValue<?> value, final Type type) {
|
|
||||||
final Object raw = value.getValueRaw();
|
|
||||||
if (raw == null) {
|
|
||||||
return DEFAULT_STRING;
|
|
||||||
}
|
|
||||||
|
|
||||||
final Type valueType = type instanceof ParameterizedType parameterizedType ? parameterizedType.getActualTypeArguments()[0] : null;
|
|
||||||
|
|
||||||
return registry.serialize(raw, valueType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
package ca.spottedleaf.moonrise.common.config.moonrise.type;
|
|
||||||
|
|
||||||
public final class DefaultedValue<T> {
|
|
||||||
|
|
||||||
private final T value;
|
|
||||||
|
|
||||||
public DefaultedValue() {
|
|
||||||
this(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DefaultedValue(final T value) {
|
|
||||||
this.value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public T getValueRaw() {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public T getOrDefault(final T dfl) {
|
|
||||||
return this.value != null ? this.value : dfl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,76 +0,0 @@
|
|||||||
package ca.spottedleaf.moonrise.common.config.type;
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
|
|
||||||
public final class Duration {
|
|
||||||
|
|
||||||
private final String string;
|
|
||||||
private final long timeNS;
|
|
||||||
|
|
||||||
private Duration(final String string, final long timeNS) {
|
|
||||||
this.string = string;
|
|
||||||
this.timeNS = timeNS;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Duration parse(final String value) {
|
|
||||||
if (value.length() < 2) {
|
|
||||||
throw new IllegalArgumentException("Invalid duration: " + value);
|
|
||||||
}
|
|
||||||
|
|
||||||
final char last = value.charAt(value.length() - 1);
|
|
||||||
|
|
||||||
final long multiplier;
|
|
||||||
|
|
||||||
switch (last) {
|
|
||||||
case 's': {
|
|
||||||
multiplier = (1000L * 1000L * 1000L) * 1L;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 't': {
|
|
||||||
multiplier = (1000L * 1000L * 1000L) / 20L;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'm': {
|
|
||||||
multiplier = (1000L * 1000L * 1000L) * 60L;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'h': {
|
|
||||||
multiplier = (1000L * 1000L * 1000L) * 60L * 60L;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'd': {
|
|
||||||
multiplier = (1000L * 1000L * 1000L) * 24L * 60L * 60L;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
throw new IllegalArgumentException("Duration must end with one of: [s, t, m, h, d]");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final BigDecimal parsed = new BigDecimal(value.substring(0, value.length() - 1))
|
|
||||||
.multiply(new BigDecimal(multiplier));
|
|
||||||
|
|
||||||
return new Duration(value, parsed.toBigInteger().longValueExact());
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getTimeNS() {
|
|
||||||
return this.timeNS;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getTimeMS() {
|
|
||||||
return this.timeNS / (1000L * 1000L);
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getTimeS() {
|
|
||||||
return this.timeNS / (1000L * 1000L * 1000L);
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getTimeTicks() {
|
|
||||||
return this.timeNS / ((1000L * 1000L * 1000L) / (20L));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return this.string;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -122,7 +122,7 @@ public final class NearbyPlayers {
|
|||||||
players[NearbyMapType.GENERAL_SMALL.ordinal()].update(chunk.x, chunk.z, GENERAL_SMALL_VIEW_DISTANCE);
|
players[NearbyMapType.GENERAL_SMALL.ordinal()].update(chunk.x, chunk.z, GENERAL_SMALL_VIEW_DISTANCE);
|
||||||
players[NearbyMapType.GENERAL_REALLY_SMALL.ordinal()].update(chunk.x, chunk.z, GENERAL_REALLY_SMALL_VIEW_DISTANCE);
|
players[NearbyMapType.GENERAL_REALLY_SMALL.ordinal()].update(chunk.x, chunk.z, GENERAL_REALLY_SMALL_VIEW_DISTANCE);
|
||||||
players[NearbyMapType.TICK_VIEW_DISTANCE.ordinal()].update(chunk.x, chunk.z, ChunkSystem.getTickViewDistance(player));
|
players[NearbyMapType.TICK_VIEW_DISTANCE.ordinal()].update(chunk.x, chunk.z, ChunkSystem.getTickViewDistance(player));
|
||||||
players[NearbyMapType.VIEW_DISTANCE.ordinal()].update(chunk.x, chunk.z, ChunkSystem.getLoadViewDistance(player));
|
players[NearbyMapType.VIEW_DISTANCE.ordinal()].update(chunk.x, chunk.z, ChunkSystem.getViewDistance(player));
|
||||||
players[NearbyMapType.SPAWN_RANGE.ordinal()].update(chunk.x, chunk.z, ChunkTickConstants.PLAYER_SPAWN_TRACK_RANGE); // Moonrise - chunk tick iteration
|
players[NearbyMapType.SPAWN_RANGE.ordinal()].update(chunk.x, chunk.z, ChunkTickConstants.PLAYER_SPAWN_TRACK_RANGE); // Moonrise - chunk tick iteration
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -152,8 +152,8 @@ public final class ChunkSystem {
|
|||||||
return RegionizedPlayerChunkLoader.getAPISendViewDistance(player);
|
return RegionizedPlayerChunkLoader.getAPISendViewDistance(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int getLoadViewDistance(final ServerPlayer player) {
|
public static int getViewDistance(final ServerPlayer player) {
|
||||||
return RegionizedPlayerChunkLoader.getLoadViewDistance(player);
|
return RegionizedPlayerChunkLoader.getAPIViewDistance(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int getTickViewDistance(final ServerPlayer player) {
|
public static int getTickViewDistance(final ServerPlayer player) {
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
package ca.spottedleaf.moonrise.common.util;
|
package ca.spottedleaf.moonrise.common.util;
|
||||||
|
|
||||||
import ca.spottedleaf.moonrise.common.PlatformHooks;
|
import ca.spottedleaf.moonrise.common.PlatformHooks;
|
||||||
import ca.spottedleaf.moonrise.common.config.adapter.TypeAdapterRegistry;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.config.YamlConfig;
|
|
||||||
import ca.spottedleaf.moonrise.common.config.moonrise.MoonriseConfig;
|
import ca.spottedleaf.moonrise.common.config.moonrise.MoonriseConfig;
|
||||||
import ca.spottedleaf.moonrise.common.config.moonrise.adapter.DefaultedTypeAdapter;
|
import ca.spottedleaf.yamlconfig.adapter.TypeAdapterRegistry;
|
||||||
import ca.spottedleaf.moonrise.common.config.moonrise.type.DefaultedValue;
|
import ca.spottedleaf.yamlconfig.config.YamlConfig;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@@ -18,8 +16,6 @@ public final class ConfigHolder {
|
|||||||
private static final TypeAdapterRegistry CONFIG_ADAPTERS = new TypeAdapterRegistry();
|
private static final TypeAdapterRegistry CONFIG_ADAPTERS = new TypeAdapterRegistry();
|
||||||
private static final YamlConfig<MoonriseConfig> CONFIG;
|
private static final YamlConfig<MoonriseConfig> CONFIG;
|
||||||
static {
|
static {
|
||||||
CONFIG_ADAPTERS.putAdapter(DefaultedValue.class, new DefaultedTypeAdapter());
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
CONFIG = new YamlConfig<>(MoonriseConfig.class, new MoonriseConfig(), CONFIG_ADAPTERS);
|
CONFIG = new YamlConfig<>(MoonriseConfig.class, new MoonriseConfig(), CONFIG_ADAPTERS);
|
||||||
} catch (final Exception ex) {
|
} catch (final Exception ex) {
|
||||||
@@ -52,14 +48,6 @@ public final class ConfigHolder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static boolean reloadConfig() {
|
public static boolean reloadConfig() {
|
||||||
final boolean ret = reloadConfig0();
|
|
||||||
|
|
||||||
CONFIG.callInitialisers();
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean reloadConfig0() {
|
|
||||||
synchronized (CONFIG) {
|
synchronized (CONFIG) {
|
||||||
if (CONFIG_FILE.exists()) {
|
if (CONFIG_FILE.exists()) {
|
||||||
try {
|
try {
|
||||||
@@ -70,6 +58,8 @@ public final class ConfigHolder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CONFIG.callInitialisers();
|
||||||
|
|
||||||
// write back any changes, or create if needed
|
// write back any changes, or create if needed
|
||||||
return saveConfig();
|
return saveConfig();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,52 +0,0 @@
|
|||||||
package ca.spottedleaf.moonrise.common.util;
|
|
||||||
|
|
||||||
import net.minecraft.world.level.levelgen.LegacyRandomSource;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Avoid costly CAS of superclass
|
|
||||||
*/
|
|
||||||
public final class SimpleRandom extends LegacyRandomSource {
|
|
||||||
|
|
||||||
private static final long MULTIPLIER = 25214903917L;
|
|
||||||
private static final long ADDEND = 11L;
|
|
||||||
private static final int BITS = 48;
|
|
||||||
private static final long MASK = (1L << BITS) - 1;
|
|
||||||
|
|
||||||
private long value;
|
|
||||||
|
|
||||||
public SimpleRandom(final long seed) {
|
|
||||||
super(0L);
|
|
||||||
this.value = seed;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setSeed(final long seed) {
|
|
||||||
this.value = (seed ^ MULTIPLIER) & MASK;
|
|
||||||
}
|
|
||||||
|
|
||||||
private long advanceSeed() {
|
|
||||||
return this.value = ((this.value * MULTIPLIER) + ADDEND) & MASK;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int next(final int bits) {
|
|
||||||
return (int)(this.advanceSeed() >>> (BITS - bits));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int nextInt() {
|
|
||||||
final long seed = this.advanceSeed();
|
|
||||||
return (int)(seed >>> (BITS - Integer.SIZE));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int nextInt(final int bound) {
|
|
||||||
if (bound <= 0) {
|
|
||||||
throw new IllegalArgumentException();
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/
|
|
||||||
final long value = this.advanceSeed() >>> (BITS - Integer.SIZE);
|
|
||||||
return (int)((value * (long)bound) >>> Integer.SIZE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,105 @@
|
|||||||
|
package ca.spottedleaf.moonrise.common.util;
|
||||||
|
|
||||||
|
import net.minecraft.util.Mth;
|
||||||
|
import net.minecraft.util.RandomSource;
|
||||||
|
import net.minecraft.world.level.levelgen.BitRandomSource;
|
||||||
|
import net.minecraft.world.level.levelgen.MarsagliaPolarGaussian;
|
||||||
|
import net.minecraft.world.level.levelgen.PositionalRandomFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Avoid costly CAS of superclass + division in nextInt
|
||||||
|
*/
|
||||||
|
public final class SimpleThreadUnsafeRandom implements BitRandomSource {
|
||||||
|
|
||||||
|
private static final long MULTIPLIER = 25214903917L;
|
||||||
|
private static final long ADDEND = 11L;
|
||||||
|
private static final int BITS = 48;
|
||||||
|
private static final long MASK = (1L << BITS) - 1L;
|
||||||
|
|
||||||
|
private long value;
|
||||||
|
private final MarsagliaPolarGaussian gaussianSource = new MarsagliaPolarGaussian(this);
|
||||||
|
|
||||||
|
public SimpleThreadUnsafeRandom(final long seed) {
|
||||||
|
this.setSeed(seed);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSeed(final long seed) {
|
||||||
|
this.value = (seed ^ MULTIPLIER) & MASK;
|
||||||
|
this.gaussianSource.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
private long advanceSeed() {
|
||||||
|
return this.value = ((this.value * MULTIPLIER) + ADDEND) & MASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int next(final int bits) {
|
||||||
|
return (int)(this.advanceSeed() >>> (BITS - bits));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int nextInt() {
|
||||||
|
final long seed = this.advanceSeed();
|
||||||
|
return (int)(seed >>> (BITS - Integer.SIZE));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int nextInt(final int bound) {
|
||||||
|
if (bound <= 0) {
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/
|
||||||
|
final long value = this.advanceSeed() >>> (BITS - Integer.SIZE);
|
||||||
|
return (int)((value * (long)bound) >>> Integer.SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double nextGaussian() {
|
||||||
|
return this.gaussianSource.nextGaussian();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RandomSource fork() {
|
||||||
|
return new SimpleThreadUnsafeRandom(this.nextLong());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PositionalRandomFactory forkPositional() {
|
||||||
|
return new SimpleRandomPositionalFactory(this.nextLong());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class SimpleRandomPositionalFactory implements PositionalRandomFactory {
|
||||||
|
|
||||||
|
private final long seed;
|
||||||
|
|
||||||
|
public SimpleRandomPositionalFactory(final long seed) {
|
||||||
|
this.seed = seed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getSeed() {
|
||||||
|
return this.seed;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RandomSource fromHashOf(final String string) {
|
||||||
|
return new SimpleThreadUnsafeRandom((long)string.hashCode() ^ this.seed);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RandomSource fromSeed(final long seed) {
|
||||||
|
return new SimpleThreadUnsafeRandom(seed);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RandomSource at(final int x, final int y, final int z) {
|
||||||
|
return new SimpleThreadUnsafeRandom(Mth.getSeed(x, y, z) ^ this.seed);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void parityConfigString(final StringBuilder stringBuilder) {
|
||||||
|
stringBuilder.append("SimpleRandomPositionalFactory{").append(this.seed).append('}');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
package ca.spottedleaf.moonrise.common.util;
|
||||||
|
|
||||||
|
import net.minecraft.util.Mth;
|
||||||
|
import net.minecraft.util.RandomSource;
|
||||||
|
import net.minecraft.world.level.levelgen.BitRandomSource;
|
||||||
|
import net.minecraft.world.level.levelgen.MarsagliaPolarGaussian;
|
||||||
|
import net.minecraft.world.level.levelgen.PositionalRandomFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Avoid costly CAS of superclass
|
||||||
|
*/
|
||||||
|
public final class ThreadUnsafeRandom implements BitRandomSource {
|
||||||
|
|
||||||
|
private static final long MULTIPLIER = 25214903917L;
|
||||||
|
private static final long ADDEND = 11L;
|
||||||
|
private static final int BITS = 48;
|
||||||
|
private static final long MASK = (1L << BITS) - 1L;
|
||||||
|
|
||||||
|
private long value;
|
||||||
|
private final MarsagliaPolarGaussian gaussianSource = new MarsagliaPolarGaussian(this);
|
||||||
|
|
||||||
|
public ThreadUnsafeRandom(final long seed) {
|
||||||
|
this.setSeed(seed);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSeed(final long seed) {
|
||||||
|
this.value = (seed ^ MULTIPLIER) & MASK;
|
||||||
|
this.gaussianSource.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
private long advanceSeed() {
|
||||||
|
return this.value = ((this.value * MULTIPLIER) + ADDEND) & MASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int next(final int bits) {
|
||||||
|
return (int)(this.advanceSeed() >>> (BITS - bits));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int nextInt() {
|
||||||
|
final long seed = this.advanceSeed();
|
||||||
|
return (int)(seed >>> (BITS - Integer.SIZE));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double nextGaussian() {
|
||||||
|
return this.gaussianSource.nextGaussian();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RandomSource fork() {
|
||||||
|
return new ThreadUnsafeRandom(this.nextLong());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PositionalRandomFactory forkPositional() {
|
||||||
|
return new ThreadUnsafeRandomPositionalFactory(this.nextLong());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class ThreadUnsafeRandomPositionalFactory implements PositionalRandomFactory {
|
||||||
|
|
||||||
|
private final long seed;
|
||||||
|
|
||||||
|
public ThreadUnsafeRandomPositionalFactory(final long seed) {
|
||||||
|
this.seed = seed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getSeed() {
|
||||||
|
return this.seed;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RandomSource fromHashOf(final String string) {
|
||||||
|
return new ThreadUnsafeRandom((long)string.hashCode() ^ this.seed);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RandomSource fromSeed(final long seed) {
|
||||||
|
return new ThreadUnsafeRandom(seed);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RandomSource at(final int x, final int y, final int z) {
|
||||||
|
return new ThreadUnsafeRandom(Mth.getSeed(x, y, z) ^ this.seed);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void parityConfigString(final StringBuilder stringBuilder) {
|
||||||
|
stringBuilder.append("ThreadUnsafeRandomPositionalFactory{").append(this.seed).append('}');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
package ca.spottedleaf.moonrise.mixin.chunk_system;
|
package ca.spottedleaf.moonrise.mixin.chunk_system;
|
||||||
|
|
||||||
|
import ca.spottedleaf.moonrise.common.util.MoonriseConstants;
|
||||||
import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel;
|
import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel;
|
||||||
import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkSystemDistanceManager;
|
import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkSystemDistanceManager;
|
||||||
import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkHolderManager;
|
import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkHolderManager;
|
||||||
@@ -13,6 +14,7 @@ import net.minecraft.server.level.ThrottlingChunkTaskDispatcher;
|
|||||||
import net.minecraft.server.level.Ticket;
|
import net.minecraft.server.level.Ticket;
|
||||||
import net.minecraft.server.level.TicketType;
|
import net.minecraft.server.level.TicketType;
|
||||||
import net.minecraft.server.level.TickingTracker;
|
import net.minecraft.server.level.TickingTracker;
|
||||||
|
import net.minecraft.util.Mth;
|
||||||
import net.minecraft.util.SortedArraySet;
|
import net.minecraft.util.SortedArraySet;
|
||||||
import net.minecraft.world.level.ChunkPos;
|
import net.minecraft.world.level.ChunkPos;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
@@ -285,7 +287,10 @@ abstract class DistanceManagerMixin implements ChunkSystemDistanceManager {
|
|||||||
*/
|
*/
|
||||||
@Overwrite
|
@Overwrite
|
||||||
public void updateSimulationDistance(final int simulationDistance) {
|
public void updateSimulationDistance(final int simulationDistance) {
|
||||||
((ChunkSystemServerLevel)this.moonrise$getChunkMap().level).moonrise$getPlayerChunkLoader().setTickDistance(simulationDistance);
|
// note: vanilla does not clamp to 0, but we do simply because we need a min of 0
|
||||||
|
final int clamped = Mth.clamp(simulationDistance, 0, MoonriseConstants.MAX_VIEW_DISTANCE);
|
||||||
|
|
||||||
|
((ChunkSystemServerLevel)this.moonrise$getChunkMap().level).moonrise$getPlayerChunkLoader().setTickDistance(clamped);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -43,4 +43,17 @@ abstract class PlayerListMixin {
|
|||||||
)
|
)
|
||||||
private void doNotAdjustVD(final PlayerList instance, final Packet<?> packet) {}
|
private void doNotAdjustVD(final PlayerList instance, final Packet<?> packet) {}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @reason The RegionizedPlayerChunkLoader will handle the SD packet
|
||||||
|
* @author Spottedleaf
|
||||||
|
*/
|
||||||
|
@Redirect(
|
||||||
|
method = "setSimulationDistance",
|
||||||
|
at = @At(
|
||||||
|
value = "INVOKE",
|
||||||
|
target = "Lnet/minecraft/server/players/PlayerList;broadcastAll(Lnet/minecraft/network/protocol/Packet;)V"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
private void doNotAdjustSD(final PlayerList instance, final Packet<?> packet) {}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -315,6 +315,22 @@ abstract class ServerChunkCacheMixin extends ChunkSource implements ChunkSystemS
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @reason We need to use {@link ChunkHolder#getChunkToSend()} as the new chunk system will not bring every chunk
|
||||||
|
* sent to players up to block ticking.
|
||||||
|
* @author Spottedleaf
|
||||||
|
*/
|
||||||
|
@Redirect(
|
||||||
|
method = "broadcastChangedChunks",
|
||||||
|
at = @At(
|
||||||
|
value = "INVOKE",
|
||||||
|
target = "Lnet/minecraft/server/level/ChunkHolder;getTickingChunk()Lnet/minecraft/world/level/chunk/LevelChunk;")
|
||||||
|
)
|
||||||
|
private LevelChunk redirectTickingChunk(final ChunkHolder instance) {
|
||||||
|
return instance.getChunkToSend();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @reason Perform mid-tick chunk task processing during chunk tick
|
* @reason Perform mid-tick chunk task processing during chunk tick
|
||||||
* @author Spottedleaf
|
* @author Spottedleaf
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package ca.spottedleaf.moonrise.mixin.chunk_tick_iteration;
|
|||||||
|
|
||||||
import ca.spottedleaf.moonrise.common.list.ReferenceList;
|
import ca.spottedleaf.moonrise.common.list.ReferenceList;
|
||||||
import ca.spottedleaf.moonrise.common.misc.NearbyPlayers;
|
import ca.spottedleaf.moonrise.common.misc.NearbyPlayers;
|
||||||
import ca.spottedleaf.moonrise.common.util.SimpleRandom;
|
import ca.spottedleaf.moonrise.common.util.SimpleThreadUnsafeRandom;
|
||||||
import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkData;
|
import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkData;
|
||||||
import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkSystemChunkHolder;
|
import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkSystemChunkHolder;
|
||||||
import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkSystemLevelChunk;
|
import ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkSystemLevelChunk;
|
||||||
@@ -39,7 +39,7 @@ abstract class ServerChunkCacheMixin extends ChunkSource {
|
|||||||
|
|
||||||
|
|
||||||
@Unique
|
@Unique
|
||||||
private final SimpleRandom shuffleRandom = new SimpleRandom(0L);
|
private final SimpleThreadUnsafeRandom shuffleRandom = new SimpleThreadUnsafeRandom(0L);
|
||||||
|
|
||||||
@Unique
|
@Unique
|
||||||
private boolean isChunkNearPlayer(final ChunkMap chunkMap, final ChunkPos chunkPos, final LevelChunk levelChunk) {
|
private boolean isChunkNearPlayer(final ChunkMap chunkMap, final ChunkPos chunkPos, final LevelChunk levelChunk) {
|
||||||
|
|||||||
@@ -5,16 +5,12 @@ import ca.spottedleaf.moonrise.patches.collisions.shape.CollisionVoxelShape;
|
|||||||
import com.mojang.serialization.MapCodec;
|
import com.mojang.serialization.MapCodec;
|
||||||
import it.unimi.dsi.fastutil.HashCommon;
|
import it.unimi.dsi.fastutil.HashCommon;
|
||||||
import it.unimi.dsi.fastutil.objects.Reference2ObjectArrayMap;
|
import it.unimi.dsi.fastutil.objects.Reference2ObjectArrayMap;
|
||||||
import net.minecraft.core.BlockPos;
|
|
||||||
import net.minecraft.core.Direction;
|
import net.minecraft.core.Direction;
|
||||||
import net.minecraft.world.level.BlockGetter;
|
|
||||||
import net.minecraft.world.level.block.Block;
|
import net.minecraft.world.level.block.Block;
|
||||||
import net.minecraft.world.level.block.state.BlockBehaviour;
|
import net.minecraft.world.level.block.state.BlockBehaviour;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
import net.minecraft.world.level.block.state.StateHolder;
|
import net.minecraft.world.level.block.state.StateHolder;
|
||||||
import net.minecraft.world.level.block.state.properties.Property;
|
import net.minecraft.world.level.block.state.properties.Property;
|
||||||
import net.minecraft.world.phys.AABB;
|
|
||||||
import net.minecraft.world.phys.shapes.CollisionContext;
|
|
||||||
import net.minecraft.world.phys.shapes.Shapes;
|
import net.minecraft.world.phys.shapes.Shapes;
|
||||||
import net.minecraft.world.phys.shapes.VoxelShape;
|
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
@@ -32,7 +28,7 @@ abstract class BlockStateBaseMixin extends StateHolder<Block, BlockState> implem
|
|||||||
protected BlockBehaviour.BlockStateBase.Cache cache;
|
protected BlockBehaviour.BlockStateBase.Cache cache;
|
||||||
|
|
||||||
@Shadow
|
@Shadow
|
||||||
public abstract VoxelShape getCollisionShape(BlockGetter blockGetter, BlockPos blockPos, CollisionContext collisionContext);
|
public abstract boolean isAir();
|
||||||
|
|
||||||
@Shadow
|
@Shadow
|
||||||
public VoxelShape[] occlusionShapesByFace;
|
public VoxelShape[] occlusionShapesByFace;
|
||||||
@@ -99,10 +95,9 @@ abstract class BlockStateBaseMixin extends StateHolder<Block, BlockState> implem
|
|||||||
private void initCollisionState(final CallbackInfo ci) {
|
private void initCollisionState(final CallbackInfo ci) {
|
||||||
if (this.cache != null) {
|
if (this.cache != null) {
|
||||||
final VoxelShape collisionShape = this.cache.collisionShape;
|
final VoxelShape collisionShape = this.cache.collisionShape;
|
||||||
try {
|
if (this.isAir()) {
|
||||||
this.constantCollisionShape = this.getCollisionShape(null, null, null);
|
this.constantCollisionShape = Shapes.empty();
|
||||||
} catch (final Throwable throwable) {
|
} else {
|
||||||
// :(
|
|
||||||
this.constantCollisionShape = null;
|
this.constantCollisionShape = null;
|
||||||
}
|
}
|
||||||
this.occludesFullBlock = ((CollisionVoxelShape)collisionShape).moonrise$occludesFullBlock();
|
this.occludesFullBlock = ((CollisionVoxelShape)collisionShape).moonrise$occludesFullBlock();
|
||||||
|
|||||||
@@ -146,7 +146,7 @@ abstract class TrackedEntityMixin implements EntityTrackerTrackedEntity {
|
|||||||
@Overwrite
|
@Overwrite
|
||||||
public int getEffectiveRange() {
|
public int getEffectiveRange() {
|
||||||
final Entity entity = this.entity;
|
final Entity entity = this.entity;
|
||||||
int range = PlatformHooks.get().modifyEntityTrackingRange(entity, this.range);
|
int range = this.range;
|
||||||
|
|
||||||
if (entity.getPassengers() == ImmutableList.<Entity>of()) {
|
if (entity.getPassengers() == ImmutableList.<Entity>of()) {
|
||||||
return this.scaledRange(range);
|
return this.scaledRange(range);
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package ca.spottedleaf.moonrise.mixin.loading_screen;
|
package ca.spottedleaf.moonrise.mixin.loading_screen;
|
||||||
|
|
||||||
|
import ca.spottedleaf.moonrise.common.util.ConfigHolder;
|
||||||
import net.minecraft.client.multiplayer.LevelLoadStatusManager;
|
import net.minecraft.client.multiplayer.LevelLoadStatusManager;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.Shadow;
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
@@ -25,6 +26,9 @@ abstract class LevelLoadStatusManagerMixin {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
private void immediatelyClose(final CallbackInfo ci) {
|
private void immediatelyClose(final CallbackInfo ci) {
|
||||||
|
if (!ConfigHolder.getConfig().misc.immediatelyCloseLoadingScreen) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (this.status == LevelLoadStatusManager.Status.WAITING_FOR_SERVER) {
|
if (this.status == LevelLoadStatusManager.Status.WAITING_FOR_SERVER) {
|
||||||
this.status = LevelLoadStatusManager.Status.LEVEL_READY;
|
this.status = LevelLoadStatusManager.Status.LEVEL_READY;
|
||||||
ci.cancel();
|
ci.cancel();
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package ca.spottedleaf.moonrise.mixin.random;
|
||||||
|
|
||||||
|
import ca.spottedleaf.moonrise.common.util.ThreadUnsafeRandom;
|
||||||
|
import net.minecraft.util.RandomSource;
|
||||||
|
import net.minecraft.world.entity.Entity;
|
||||||
|
import net.minecraft.world.level.levelgen.RandomSupport;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||||
|
|
||||||
|
@Mixin(Entity.class)
|
||||||
|
abstract class EntityMixin {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @reason Changes Entity#random to use ThreadUnsafeRandom, skipping the thread checks and CAS logic
|
||||||
|
* @author Spottedleadf
|
||||||
|
*/
|
||||||
|
@Redirect(
|
||||||
|
method = "<init>",
|
||||||
|
at = @At(
|
||||||
|
value = "INVOKE",
|
||||||
|
target = "Lnet/minecraft/util/RandomSource;create()Lnet/minecraft/util/RandomSource;"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
private RandomSource redirectEntityRandom() {
|
||||||
|
return new ThreadUnsafeRandom(RandomSupport.generateUniqueSeed());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package ca.spottedleaf.moonrise.mixin.random;
|
||||||
|
|
||||||
|
import ca.spottedleaf.moonrise.common.util.ThreadUnsafeRandom;
|
||||||
|
import net.minecraft.util.RandomSource;
|
||||||
|
import net.minecraft.world.level.Level;
|
||||||
|
import net.minecraft.world.level.levelgen.RandomSupport;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||||
|
|
||||||
|
@Mixin(Level.class)
|
||||||
|
abstract class LevelMixin {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @reason Changes Level#random to use ThreadUnsafeRandom, skipping the thread checks and CAS logic
|
||||||
|
* @author Spottedleadf
|
||||||
|
*/
|
||||||
|
@Redirect(
|
||||||
|
method = "<init>",
|
||||||
|
at = @At(
|
||||||
|
value = "INVOKE",
|
||||||
|
target = "Lnet/minecraft/util/RandomSource;create()Lnet/minecraft/util/RandomSource;"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
private RandomSource redirectLevelRandom() {
|
||||||
|
return new ThreadUnsafeRandom(RandomSupport.generateUniqueSeed());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,7 +2,7 @@ package ca.spottedleaf.moonrise.mixin.random_ticking;
|
|||||||
|
|
||||||
import ca.spottedleaf.moonrise.common.PlatformHooks;
|
import ca.spottedleaf.moonrise.common.PlatformHooks;
|
||||||
import ca.spottedleaf.moonrise.common.list.ShortList;
|
import ca.spottedleaf.moonrise.common.list.ShortList;
|
||||||
import ca.spottedleaf.moonrise.common.util.SimpleRandom;
|
import ca.spottedleaf.moonrise.common.util.SimpleThreadUnsafeRandom;
|
||||||
import ca.spottedleaf.moonrise.common.util.WorldUtil;
|
import ca.spottedleaf.moonrise.common.util.WorldUtil;
|
||||||
import ca.spottedleaf.moonrise.patches.block_counting.BlockCountingChunkSection;
|
import ca.spottedleaf.moonrise.patches.block_counting.BlockCountingChunkSection;
|
||||||
import com.llamalad7.mixinextras.sugar.Local;
|
import com.llamalad7.mixinextras.sugar.Local;
|
||||||
@@ -20,6 +20,7 @@ import net.minecraft.world.level.chunk.LevelChunk;
|
|||||||
import net.minecraft.world.level.chunk.LevelChunkSection;
|
import net.minecraft.world.level.chunk.LevelChunkSection;
|
||||||
import net.minecraft.world.level.chunk.PalettedContainer;
|
import net.minecraft.world.level.chunk.PalettedContainer;
|
||||||
import net.minecraft.world.level.dimension.DimensionType;
|
import net.minecraft.world.level.dimension.DimensionType;
|
||||||
|
import net.minecraft.world.level.levelgen.RandomSupport;
|
||||||
import net.minecraft.world.level.material.FluidState;
|
import net.minecraft.world.level.material.FluidState;
|
||||||
import net.minecraft.world.level.storage.WritableLevelData;
|
import net.minecraft.world.level.storage.WritableLevelData;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
@@ -38,7 +39,7 @@ abstract class ServerLevelMixin extends Level implements WorldGenLevel {
|
|||||||
private static final LevelChunkSection[] EMPTY_SECTION_ARRAY = new LevelChunkSection[0];
|
private static final LevelChunkSection[] EMPTY_SECTION_ARRAY = new LevelChunkSection[0];
|
||||||
|
|
||||||
@Unique
|
@Unique
|
||||||
private final SimpleRandom simpleRandom = new SimpleRandom(0L);
|
private final SimpleThreadUnsafeRandom simpleRandom = new SimpleThreadUnsafeRandom(RandomSupport.generateUniqueSeed());
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @reason Use faster random
|
* @reason Use faster random
|
||||||
@@ -72,7 +73,7 @@ abstract class ServerLevelMixin extends Level implements WorldGenLevel {
|
|||||||
@Local(ordinal = 0, argsOnly = true) final int tickSpeed) {
|
@Local(ordinal = 0, argsOnly = true) final int tickSpeed) {
|
||||||
final LevelChunkSection[] sections = chunk.getSections();
|
final LevelChunkSection[] sections = chunk.getSections();
|
||||||
final int minSection = WorldUtil.getMinSection((ServerLevel)(Object)this);
|
final int minSection = WorldUtil.getMinSection((ServerLevel)(Object)this);
|
||||||
final SimpleRandom simpleRandom = this.simpleRandom;
|
final SimpleThreadUnsafeRandom simpleRandom = this.simpleRandom;
|
||||||
final boolean doubleTickFluids = !PlatformHooks.get().configFixMC224294();
|
final boolean doubleTickFluids = !PlatformHooks.get().configFixMC224294();
|
||||||
|
|
||||||
final ChunkPos cpos = chunk.getPos();
|
final ChunkPos cpos = chunk.getPos();
|
||||||
|
|||||||
@@ -1214,16 +1214,9 @@ public final class MoonriseRegionFileIO {
|
|||||||
try {
|
try {
|
||||||
writeData = this.regionDataController.startWrite(this.chunkX, this.chunkZ, write);
|
writeData = this.regionDataController.startWrite(this.chunkX, this.chunkZ, write);
|
||||||
} catch (final Throwable thr) {
|
} catch (final Throwable thr) {
|
||||||
// TODO implement this?
|
|
||||||
/*if (thr instanceof RegionFileStorage.RegionFileSizeException) {
|
|
||||||
final int maxSize = RegionFile.MAX_CHUNK_SIZE / (1024 * 1024);
|
|
||||||
LOGGER.error("Chunk at (" + this.chunkX + "," + this.chunkZ + ") in '" + WorldUtil.getWorldName(this.world) + "' exceeds max size of " + maxSize + "MiB, it has been deleted from disk.");
|
|
||||||
} else */
|
|
||||||
{
|
|
||||||
failedWrite = thr instanceof IOException;
|
failedWrite = thr instanceof IOException;
|
||||||
LOGGER.error("Failed to write chunk data for task: " + this.toString(), thr);
|
LOGGER.error("Failed to write chunk data for task: " + this.toString(), thr);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (writeData == null) {
|
if (writeData == null) {
|
||||||
// null if a throwable was encountered
|
// null if a throwable was encountered
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import ca.spottedleaf.moonrise.common.PlatformHooks;
|
|||||||
import ca.spottedleaf.moonrise.common.misc.AllocatingRateLimiter;
|
import ca.spottedleaf.moonrise.common.misc.AllocatingRateLimiter;
|
||||||
import ca.spottedleaf.moonrise.common.misc.SingleUserAreaMap;
|
import ca.spottedleaf.moonrise.common.misc.SingleUserAreaMap;
|
||||||
import ca.spottedleaf.moonrise.common.util.CoordinateUtils;
|
import ca.spottedleaf.moonrise.common.util.CoordinateUtils;
|
||||||
|
import ca.spottedleaf.moonrise.common.util.MoonriseConstants;
|
||||||
import ca.spottedleaf.moonrise.common.util.TickThread;
|
import ca.spottedleaf.moonrise.common.util.TickThread;
|
||||||
import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemLevel;
|
import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemLevel;
|
||||||
import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel;
|
import ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel;
|
||||||
@@ -114,14 +115,25 @@ public final class RegionizedPlayerChunkLoader {
|
|||||||
int sendViewDistance
|
int sendViewDistance
|
||||||
) {
|
) {
|
||||||
public ViewDistances setTickViewDistance(final int distance) {
|
public ViewDistances setTickViewDistance(final int distance) {
|
||||||
|
if (distance != -1 && (distance < (0) || distance > (MoonriseConstants.MAX_VIEW_DISTANCE))) {
|
||||||
|
throw new IllegalArgumentException(Integer.toString(distance));
|
||||||
|
}
|
||||||
return new ViewDistances(distance, this.loadViewDistance, this.sendViewDistance);
|
return new ViewDistances(distance, this.loadViewDistance, this.sendViewDistance);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ViewDistances setLoadViewDistance(final int distance) {
|
public ViewDistances setLoadViewDistance(final int distance) {
|
||||||
|
// note: load view distance = api view distance + 1
|
||||||
|
if (distance != -1 && (distance < (2 + 1) || distance > (MoonriseConstants.MAX_VIEW_DISTANCE + 1))) {
|
||||||
|
throw new IllegalArgumentException(Integer.toString(distance));
|
||||||
|
}
|
||||||
return new ViewDistances(this.tickViewDistance, distance, this.sendViewDistance);
|
return new ViewDistances(this.tickViewDistance, distance, this.sendViewDistance);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ViewDistances setSendViewDistance(final int distance) {
|
public ViewDistances setSendViewDistance(final int distance) {
|
||||||
|
// note: send view distance <= load view distance - 1
|
||||||
|
if (distance != -1 && (distance < (0) || distance > (MoonriseConstants.MAX_VIEW_DISTANCE))) {
|
||||||
|
throw new IllegalArgumentException(Integer.toString(distance));
|
||||||
|
}
|
||||||
return new ViewDistances(this.tickViewDistance, this.loadViewDistance, distance);
|
return new ViewDistances(this.tickViewDistance, this.loadViewDistance, distance);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,16 +167,6 @@ public final class RegionizedPlayerChunkLoader {
|
|||||||
return data.lastLoadDistance - 1;
|
return data.lastLoadDistance - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int getLoadViewDistance(final ServerPlayer player) {
|
|
||||||
final ServerLevel level = player.serverLevel();
|
|
||||||
final PlayerChunkLoaderData data = ((ChunkSystemServerPlayer)player).moonrise$getChunkLoader();
|
|
||||||
if (data == null) {
|
|
||||||
return ((ChunkSystemServerLevel)level).moonrise$getPlayerChunkLoader().getAPIViewDistance();
|
|
||||||
}
|
|
||||||
// view distance = load distance + 1
|
|
||||||
return data.lastLoadDistance - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int getAPISendViewDistance(final ServerPlayer player) {
|
public static int getAPISendViewDistance(final ServerPlayer player) {
|
||||||
final ServerLevel level = player.serverLevel();
|
final ServerLevel level = player.serverLevel();
|
||||||
final PlayerChunkLoaderData data = ((ChunkSystemServerPlayer)player).moonrise$getChunkLoader();
|
final PlayerChunkLoaderData data = ((ChunkSystemServerPlayer)player).moonrise$getChunkLoader();
|
||||||
@@ -516,7 +518,7 @@ public final class RegionizedPlayerChunkLoader {
|
|||||||
final int playerLoadViewDistance, final int worldLoadViewDistance) {
|
final int playerLoadViewDistance, final int worldLoadViewDistance) {
|
||||||
return Math.min(
|
return Math.min(
|
||||||
playerTickViewDistance < 0 ? worldTickViewDistance : playerTickViewDistance,
|
playerTickViewDistance < 0 ? worldTickViewDistance : playerTickViewDistance,
|
||||||
playerLoadViewDistance < 0 ? worldLoadViewDistance : playerLoadViewDistance
|
playerLoadViewDistance < 0 ? (worldLoadViewDistance - 1) : (playerLoadViewDistance - 1)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -579,7 +579,7 @@ public final class ChunkTaskScheduler {
|
|||||||
this.chunkHolderManager.processTicketUpdates();
|
this.chunkHolderManager.processTicketUpdates();
|
||||||
}
|
}
|
||||||
|
|
||||||
final Consumer<ChunkAccess> loadCallback = (final ChunkAccess chunk) -> {
|
final Consumer<ChunkAccess> loadCallback = onComplete == null && !addTicket ? null : (final ChunkAccess chunk) -> {
|
||||||
try {
|
try {
|
||||||
if (onComplete != null) {
|
if (onComplete != null) {
|
||||||
onComplete.accept(chunk);
|
onComplete.accept(chunk);
|
||||||
@@ -616,9 +616,11 @@ public final class ChunkTaskScheduler {
|
|||||||
if (!chunkHolder.upgradeGenTarget(toStatus)) {
|
if (!chunkHolder.upgradeGenTarget(toStatus)) {
|
||||||
this.schedule(chunkX, chunkZ, toStatus, chunkHolder, tasks);
|
this.schedule(chunkX, chunkZ, toStatus, chunkHolder, tasks);
|
||||||
}
|
}
|
||||||
|
if (loadCallback != null) {
|
||||||
chunkHolder.addStatusConsumer(toStatus, loadCallback);
|
chunkHolder.addStatusConsumer(toStatus, loadCallback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} finally {
|
} finally {
|
||||||
this.schedulingLockArea.unlock(schedulingLock);
|
this.schedulingLockArea.unlock(schedulingLock);
|
||||||
}
|
}
|
||||||
@@ -630,7 +632,7 @@ public final class ChunkTaskScheduler {
|
|||||||
tasks.get(i).schedule();
|
tasks.get(i).schedule();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!scheduled) {
|
if (loadCallback != null && !scheduled) {
|
||||||
// couldn't schedule
|
// couldn't schedule
|
||||||
try {
|
try {
|
||||||
loadCallback.accept(chunk);
|
loadCallback.accept(chunk);
|
||||||
|
|||||||
@@ -2168,10 +2168,16 @@ public final class CollisionUtil {
|
|||||||
|
|
||||||
public CollisionContext getDelegate() {
|
public CollisionContext getDelegate() {
|
||||||
this.delegated = true;
|
this.delegated = true;
|
||||||
final Entity entity = this.getEntity();
|
final Entity entity = super.getEntity();
|
||||||
return this.delegate == null ? this.delegate = (entity == null ? CollisionContext.empty() : CollisionContext.of(entity)) : this.delegate;
|
return this.delegate == null ? this.delegate = (entity == null ? CollisionContext.empty() : CollisionContext.of(entity)) : this.delegate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Entity getEntity() {
|
||||||
|
this.getDelegate();
|
||||||
|
return super.getEntity();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isDescending() {
|
public boolean isDescending() {
|
||||||
return this.getDelegate().isDescending();
|
return this.getDelegate().isDescending();
|
||||||
|
|||||||
@@ -237,7 +237,7 @@ public final class MoonriseCommand {
|
|||||||
return Command.SINGLE_SUCCESS;
|
return Command.SINGLE_SUCCESS;
|
||||||
} else {
|
} else {
|
||||||
ctx.getSource().sendFailure(
|
ctx.getSource().sendFailure(
|
||||||
Component.literal("Reloaded Moonrise config.")
|
Component.literal("Failed to reload Moonrise config, see logs.")
|
||||||
.withStyle(ChatFormatting.RED)
|
.withStyle(ChatFormatting.RED)
|
||||||
);
|
);
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -99,6 +99,8 @@
|
|||||||
"poi_lookup.AcquirePoiMixin",
|
"poi_lookup.AcquirePoiMixin",
|
||||||
"poi_lookup.PoiManagerMixin",
|
"poi_lookup.PoiManagerMixin",
|
||||||
"poi_lookup.PortalForcerMixin",
|
"poi_lookup.PortalForcerMixin",
|
||||||
|
"random.EntityMixin",
|
||||||
|
"random.LevelMixin",
|
||||||
"random_ticking.BiomeManagerMixin",
|
"random_ticking.BiomeManagerMixin",
|
||||||
"random_ticking.BiomeMixin",
|
"random_ticking.BiomeMixin",
|
||||||
"random_ticking.LevelMixin",
|
"random_ticking.LevelMixin",
|
||||||
|
|||||||
Reference in New Issue
Block a user