9
0
mirror of https://github.com/LeavesMC/Leaves.git synced 2025-12-28 19:39:22 +00:00

Configurable force peaceful mode switch type list (#423)

This commit is contained in:
violetc
2025-03-19 10:49:35 +08:00
parent 4b9f5de695
commit 0fbd5317a4
11 changed files with 177 additions and 62 deletions

View File

@@ -4,6 +4,7 @@ import com.destroystokyo.paper.util.SneakyThrow;
import io.papermc.paper.configuration.GlobalConfiguration;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Entity;
import org.bukkit.command.Command;
import org.bukkit.configuration.file.YamlConfiguration;
import org.jetbrains.annotations.NotNull;
@@ -24,14 +25,18 @@ import org.leavesmc.leaves.protocol.CarpetServerProtocol.CarpetRules;
import org.leavesmc.leaves.protocol.bladeren.BladerenProtocol.LeavesFeature;
import org.leavesmc.leaves.protocol.bladeren.BladerenProtocol.LeavesFeatureSet;
import org.leavesmc.leaves.region.RegionFileFormat;
import org.leavesmc.leaves.util.ForcePeacefulModeSwitchType;
import org.leavesmc.leaves.util.MathUtils;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Random;
import java.util.Set;
public final class LeavesConfig {
@@ -531,14 +536,38 @@ public final class LeavesConfig {
@GlobalConfig("fast-resume")
public boolean fastResume = false;
@GlobalConfig(value = "force-peaceful-mode", validator = ForcePeacefulModeValidator.class)
public int forcePeacefulMode = -1;
public ForcePeacefulModeSwitchConfig peacefulModeSwitch = new ForcePeacefulModeSwitchConfig();
private static class ForcePeacefulModeValidator extends IntConfigValidator {
@Override
public void verify(Integer old, Integer value) throws IllegalArgumentException {
for (ServerLevel level : MinecraftServer.getServer().getAllLevels()) {
level.chunkSource.peacefulModeSwitchTick = value;
@GlobalConfigCategory("force-peaceful-mode-switch")
public static class ForcePeacefulModeSwitchConfig {
@RemovedConfig(name = "force-peaceful-mode", category = "modify", transform = true)
@GlobalConfig(value = "tick", validator = TickValidator.class)
public int tick = -1;
private static class TickValidator extends IntConfigValidator {
@Override
public void verify(Integer old, Integer value) throws IllegalArgumentException {
for (ServerLevel level : MinecraftServer.getServer().getAllLevels()) {
level.chunkSource.peacefulModeSwitchTick = value;
}
}
}
@GlobalConfig(value = "types", validator = TypeValidator.class)
public List<ForcePeacefulModeSwitchType> types = List.of(ForcePeacefulModeSwitchType.BLAZE, ForcePeacefulModeSwitchType.WITHER, ForcePeacefulModeSwitchType.SHULKER, ForcePeacefulModeSwitchType.WARDEN);
public Set<Class<? extends Entity>> classTypes = new HashSet<>();
private static class TypeValidator extends ListConfigValidator.ENUM<ForcePeacefulModeSwitchType> {
@Override
public void verify(List<ForcePeacefulModeSwitchType> old, @NotNull List<ForcePeacefulModeSwitchType> value) throws IllegalArgumentException {
Set<Class<? extends Entity>> classes = new HashSet<>();
for (ForcePeacefulModeSwitchType type : value) {
classes.add(type.getEntityClass());
}
LeavesConfig.modify.peacefulModeSwitch.classTypes = classes;
for (ServerLevel level : MinecraftServer.getServer().getAllLevels()) {
level.chunkSource.peacefulModeSwitchEntityTypes = classes;
}
}
}
}

View File

@@ -23,11 +23,6 @@ public class AutoConfigTransformer implements ConfigTransformer<Object, Object>
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public Class<Object> getFieldClass() {
throw new UnsupportedOperationException("Not supported yet.");
}
@SuppressWarnings({"unchecked", "rawtypes"})
public static class SimpleConfigTransformer implements ConfigTransformer<Object, Object> {
@@ -56,10 +51,5 @@ public class AutoConfigTransformer implements ConfigTransformer<Object, Object>
public Object saveConvert(Object value) {
return validator.saveConvert(value);
}
@Override
public Class<Object> getFieldClass() {
return validator.getFieldClass();
}
}
}

View File

@@ -42,6 +42,8 @@ public final class AutoConfigValidator implements ConfigValidator<Object> {
if (typeArgs.length > 0 && typeArgs[0] instanceof Class<?> genericClass) {
if (genericClass.equals(String.class)) {
return new ConfigValidatorImpl.ListConfigValidator.STRING();
} else if (genericClass.isEnum()) {
return new ConfigValidatorImpl.ListConfigValidator.ENUM<>((Class<Enum>) genericClass);
}
throw new IllegalArgumentException("List type " + genericClass.getTypeName() + " is not supported.");
}
@@ -60,9 +62,4 @@ public final class AutoConfigValidator implements ConfigValidator<Object> {
public Object stringConvert(String value) throws IllegalArgumentException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public Class<Object> getFieldClass() {
throw new UnsupportedOperationException("Not supported yet.");
}
}

View File

@@ -16,6 +16,4 @@ public interface ConfigConverter<E> {
default Object saveConvert(E value) {
return value;
}
Class<E> getFieldClass();
}

View File

@@ -7,29 +7,12 @@ import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.function.Function;
import java.util.stream.Collectors;
public abstract class ConfigValidatorImpl<E> implements ConfigValidator<E> {
protected Class<E> fieldClass;
@SuppressWarnings("unchecked")
public ConfigValidatorImpl() {
Type superClass = getClass().getGenericSuperclass();
if (superClass instanceof ParameterizedType) {
Type[] actualTypeArguments = ((ParameterizedType) superClass).getActualTypeArguments();
if (actualTypeArguments[0] instanceof Class) {
this.fieldClass = (Class<E>) actualTypeArguments[0];
}
}
}
@Override
public Class<E> getFieldClass() {
return fieldClass;
}
public static class BooleanConfigValidator extends ConfigValidatorImpl<Boolean> {
@Override
public Boolean stringConvert(String value) throws IllegalArgumentException {
return Boolean.parseBoolean(value);
@@ -63,21 +46,68 @@ public abstract class ConfigValidatorImpl<E> implements ConfigValidator<E> {
}
public abstract static class ListConfigValidator<E> extends ConfigValidatorImpl<List<E>> {
public static class STRING extends ListConfigValidator<String> {
public STRING() {
super(new StringConfigValidator());
}
}
public static class ENUM<E extends Enum<E>> extends ListConfigValidator<E> {
public ENUM() {
super(null);
this.elementValidator = new EnumConfigValidator<E>(getTypeArgument(getClass(), ENUM.class, Class::isEnum));
}
public ENUM(@NotNull Class<E> enumClass) {
super(new EnumConfigValidator<>(enumClass));
}
}
protected ConfigValidator<E> elementValidator;
public ListConfigValidator(ConfigValidator<E> elementValidator) {
this.elementValidator = elementValidator;
}
@Override
public List<E> loadConvert(Object value) throws IllegalArgumentException {
if (elementValidator == null) {
throw new IllegalArgumentException("element validator is null");
}
if (value instanceof List<?> list) {
return list.stream().map(elementValidator::loadConvert).collect(Collectors.toList());
} else {
throw new IllegalArgumentException("value is not a list");
}
}
@Override
public Object saveConvert(List<E> value) {
if (elementValidator == null) {
throw new IllegalArgumentException("element validator is null");
}
return value.stream().map(elementValidator::saveConvert).collect(Collectors.toList());
}
@Override
public List<E> stringConvert(String value) throws IllegalArgumentException {
throw new IllegalArgumentException("not support"); // TODO
}
@Override
public List<String> valueSuggest() {
return List.of("<NOT SUPPORT>");
}
}
public static class EnumConfigValidator<E extends Enum<E>> extends ConfigValidatorImpl<E> {
protected Class<E> enumClass;
private final List<String> enumValues;
public EnumConfigValidator(@NotNull Class<E> enumClass) {
this.fieldClass = enumClass;
this.enumClass = enumClass;
this.enumValues = new ArrayList<>() {{
for (E e : enumClass.getEnumConstants()) {
add(e.name().toLowerCase(Locale.ROOT));
@@ -86,8 +116,9 @@ public abstract class ConfigValidatorImpl<E> implements ConfigValidator<E> {
}
public EnumConfigValidator() {
this.enumClass = getTypeArgument(getClass(), EnumConfigValidator.class, Class::isEnum);
this.enumValues = new ArrayList<>() {{
for (E e : fieldClass.getEnumConstants()) {
for (E e : enumClass.getEnumConstants()) {
add(e.name().toLowerCase(Locale.ROOT));
}
}};
@@ -95,7 +126,7 @@ public abstract class ConfigValidatorImpl<E> implements ConfigValidator<E> {
@Override
public E stringConvert(@NotNull String value) throws IllegalArgumentException {
return Enum.valueOf(getFieldClass(), value.toUpperCase(Locale.ROOT));
return Enum.valueOf(enumClass, value.toUpperCase(Locale.ROOT));
}
@Override
@@ -113,4 +144,22 @@ public abstract class ConfigValidatorImpl<E> implements ConfigValidator<E> {
return enumValues;
}
}
@SuppressWarnings("unchecked")
private static <E> Class<E> getTypeArgument(Class<?> startClass, Class<?> rawType, Function<Class<?>, Boolean> check) {
Type currentClass = startClass;
while (currentClass instanceof Class<?> clazz) {
Type genericSuperclass = clazz.getGenericSuperclass();
if (genericSuperclass instanceof ParameterizedType parameterizedType) {
if (rawType.equals(parameterizedType.getRawType())) {
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
if (actualTypeArguments.length > 0 && actualTypeArguments[0] instanceof Class<?> parameterizedClass && (check == null || check.apply(parameterizedClass))) {
return (Class<E>) parameterizedClass;
}
}
}
currentClass = genericSuperclass;
}
throw new IllegalArgumentException("Can't find type argument of " + startClass.getName() + " for " + rawType.getName());
}
}

View File

@@ -103,12 +103,8 @@ public class GlobalConfigManager {
throw new IllegalArgumentException("?");
}
if (savedValue.getClass() != validator.getFieldClass()) {
savedValue = validator.loadConvert(savedValue);
}
savedValue = validator.loadConvert(savedValue);
validator.verify(null, savedValue);
field.set(upstreamField, savedValue);
} catch (IllegalArgumentException | ClassCastException e) {
LeavesConfig.config.set(path, defValue);

View File

@@ -48,10 +48,7 @@ public record VerifiedConfig(ConfigValidator<? super Object> validator, boolean
Object savedValue = LeavesConfig.config.get(path);
try {
if (savedValue != null) {
if (validator.getFieldClass() != savedValue.getClass()) {
savedValue = validator.loadConvert(savedValue);
}
savedValue = validator.loadConvert(savedValue);
if (!savedValue.equals(value)) {
return value.toString() + "(" + savedValue + " after restart)";
}

View File

@@ -16,9 +16,7 @@ public record VerifiedRemovedConfig(ConfigTransformer<? super Object, ? super Ob
Object savedValue = LeavesConfig.config.get(path);
if (savedValue != null) {
try {
if (savedValue.getClass() != transformer.getFieldClass()) {
savedValue = transformer.loadConvert(savedValue);
}
savedValue = transformer.loadConvert(savedValue);
savedValue = transformer.transform(savedValue);
field.set(upstreamField, savedValue);
} catch (IllegalAccessException | IllegalArgumentException e) {

View File

@@ -0,0 +1,61 @@
package org.leavesmc.leaves.util;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.monster.*;
import net.minecraft.world.entity.monster.breeze.Breeze;
import net.minecraft.world.entity.monster.hoglin.Hoglin;
import net.minecraft.world.entity.monster.piglin.Piglin;
import net.minecraft.world.entity.monster.piglin.PiglinBrute;
import net.minecraft.world.entity.monster.warden.Warden;
import net.minecraft.world.entity.boss.wither.WitherBoss;
public enum ForcePeacefulModeSwitchType {
BLAZE(Blaze.class),
CREEPER(Creeper.class),
DROWNED(Drowned.class),
ELDER_GUARDIAN(ElderGuardian.class),
ENDERMAN(EnderMan.class),
ENDERMITE(Endermite.class),
EVOKER(Evoker.class),
GHAST(Ghast.class),
GIANT(Giant.class),
GUARDIAN(Guardian.class),
HOGLIN(Hoglin.class),
HUSK(Husk.class),
ILLUSIONER(Illusioner.class),
MAGMA_CUBE(MagmaCube.class),
PHANTOM(Phantom.class),
PIGLIN(Piglin.class),
PIGLIN_BRUTE(PiglinBrute.class),
PILLAGER(Pillager.class),
RAVAGER(Ravager.class),
SHULKER(Shulker.class),
SILVERFISH(Silverfish.class),
SKELETON(Skeleton.class),
SLIME(Slime.class),
SPIDER(Spider.class),
STRAY(Stray.class),
VEX(Vex.class),
VINDICATOR(Vindicator.class),
WARDEN(Warden.class),
WITCH(Witch.class),
WITHER_SKELETON(WitherSkeleton.class),
ZOGLIN(Zoglin.class),
ZOMBIE(Zombie.class),
ZOMBIE_VILLAGER(ZombieVillager.class),
ZOMBIFIED_PIGLIN(ZombifiedPiglin.class),
WITHER(WitherBoss.class),
CAVE_SPIDER(CaveSpider.class),
BREEZE(Breeze.class),
BOGGED(Bogged.class);
private final Class<? extends Entity> entityClass;
ForcePeacefulModeSwitchType(Class<? extends Entity> entityClass) {
this.entityClass = entityClass;
}
public Class<? extends Entity> getEntityClass() {
return entityClass;
}
}