9
0
mirror of https://github.com/Xiao-MoMi/craft-engine.git synced 2025-12-30 20:39:10 +00:00

添加高斯分布和最大耐久值

This commit is contained in:
XiaoMoMi
2025-08-27 21:06:58 +08:00
parent b97f1c0b64
commit 36180e31d5
7 changed files with 160 additions and 3 deletions

View File

@@ -45,6 +45,7 @@ public final class ItemDataModifiers {
public static final Key UNBREAKABLE = Key.of("craftengine:unbreakable");
public static final Key DYNAMIC_LORE = Key.of("craftengine:dynamic-lore");
public static final Key OVERWRITABLE_LORE = Key.of("craftengine:overwritable-lore");
public static final Key MAX_DAMAGE = Key.of("craftengine:max-damage");
public static <T> void register(Key key, ItemDataModifierFactory<T> factory) {
((WritableRegistry<ItemDataModifierFactory<?>>) BuiltInRegistries.ITEM_DATA_MODIFIER_FACTORY)
@@ -83,6 +84,7 @@ public final class ItemDataModifiers {
register(COMPONENTS, ComponentsModifier.FACTORY);
register(REMOVE_COMPONENTS, RemoveComponentModifier.FACTORY);
register(FOOD, FoodModifier.FACTORY);
register(MAX_DAMAGE, MaxDamageModifier.FACTORY);
} else {
register(CUSTOM_NAME, CustomNameModifier.FACTORY);
register(ITEM_NAME, CustomNameModifier.FACTORY);

View File

@@ -0,0 +1,45 @@
package net.momirealms.craftengine.core.item.modifier;
import net.momirealms.craftengine.core.item.ComponentKeys;
import net.momirealms.craftengine.core.item.Item;
import net.momirealms.craftengine.core.item.ItemBuildContext;
import net.momirealms.craftengine.core.item.ItemDataModifierFactory;
import net.momirealms.craftengine.core.plugin.context.number.NumberProvider;
import net.momirealms.craftengine.core.plugin.context.number.NumberProviders;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
import org.jetbrains.annotations.Nullable;
public class MaxDamageModifier<I> implements SimpleNetworkItemDataModifier<I> {
public static final Factory<?> FACTORY = new Factory<>();
private final NumberProvider argument;
public MaxDamageModifier(NumberProvider argument) {
this.argument = argument;
}
@Override
public Key type() {
return ItemDataModifiers.MAX_DAMAGE;
}
@Override
public Item<I> apply(Item<I> item, ItemBuildContext context) {
item.maxDamage(argument.getInt(context));
return item;
}
@Override
public @Nullable Key componentType(Item<I> item, ItemBuildContext context) {
return ComponentKeys.MAX_DAMAGE;
}
public static class Factory<I> implements ItemDataModifierFactory<I> {
@Override
public ItemDataModifier<I> create(Object arg) {
NumberProvider numberProvider = NumberProviders.fromObject(arg);
return new MaxDamageModifier<>(numberProvider);
}
}
}

View File

@@ -90,11 +90,11 @@ public abstract class AbstractRecipeSerializer<T, R extends Recipe<T>> implement
if (resultMap == null) {
return null;
}
String id = ResourceConfigUtils.requireNonEmptyStringOrThrow(resultMap.get("id"), "warning.config.recipe.visual_result.missing_id");
String id = ResourceConfigUtils.requireNonEmptyStringOrThrow(resultMap.get("id"), "warning.config.recipe.result.missing_id");
int count = ResourceConfigUtils.getAsInt(resultMap.getOrDefault("count", 1), "count");
BuildableItem<T> resultItem = (BuildableItem<T>) CraftEngine.instance().itemManager().getBuildableItem(Key.of(id)).orElseThrow(() -> new LocalizedResourceConfigException("warning.config.recipe.invalid_visual_result", id));
BuildableItem<T> resultItem = (BuildableItem<T>) CraftEngine.instance().itemManager().getBuildableItem(Key.of(id)).orElseThrow(() -> new LocalizedResourceConfigException("warning.config.recipe.invalid_result", id));
if (resultItem.isEmpty()) {
throw new LocalizedResourceConfigException("warning.config.recipe.invalid_visual_result", id);
throw new LocalizedResourceConfigException("warning.config.recipe.invalid_result", id);
}
List<PostProcessor<T>> processors = ResourceConfigUtils.parseConfigAsList(resultMap.get("post-processors"), PostProcessors::fromMap);
return new CustomRecipeResult<>(

View File

@@ -0,0 +1,104 @@
package net.momirealms.craftengine.core.plugin.context.number;
import net.momirealms.craftengine.core.plugin.context.Context;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.MCUtils;
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;
public class GaussianNumberProvider implements NumberProvider {
public static final FactoryImpl FACTORY = new FactoryImpl();
private final double min;
private final double max;
private final double mean;
private final double stdDev;
private final int maxAttempts;
public GaussianNumberProvider(double min, double max, double mean, double stdDev, int maxAttempts) {
this.min = min;
this.max = max;
this.mean = mean;
this.stdDev = stdDev;
this.maxAttempts = maxAttempts;
validateParameters();
}
private void validateParameters() {
if (this.min >= this.max) {
throw new IllegalArgumentException("min must be less than max");
}
if (this.stdDev <= 0) {
throw new IllegalArgumentException("std-dev must be greater than 0");
}
if (this.maxAttempts <= 0) {
throw new IllegalArgumentException("max-attempts must be greater than 0");
}
}
@Override
public float getFloat(Context context) {
return (float) getDouble(context);
}
@Override
public double getDouble(Context context) {
Random random = ThreadLocalRandom.current();
int attempts = 0;
while (attempts < maxAttempts) {
double value = random.nextGaussian() * stdDev + mean;
if (value >= min && value <= max) {
return value;
}
attempts++;
}
return MCUtils.clamp(this.mean, this.min, this.max);
}
@Override
public Key type() {
return NumberProviders.GAUSSIAN;
}
public double min() {
return min;
}
public double max() {
return max;
}
public int maxAttempts() {
return maxAttempts;
}
public double mean() {
return mean;
}
public double stdDev() {
return stdDev;
}
public static class FactoryImpl implements NumberProviderFactory {
@Override
public NumberProvider create(Map<String, Object> arguments) {
double min = ResourceConfigUtils.getAsDouble(ResourceConfigUtils.requireNonNullOrThrow(arguments.get("min"), "warning.config.number.gaussian.missing_min"), "min");
double max = ResourceConfigUtils.getAsDouble(ResourceConfigUtils.requireNonNullOrThrow(arguments.get("max"), "warning.config.number.gaussian.missing_max"), "max");
double mean = ResourceConfigUtils.getAsDouble(arguments.getOrDefault("mean", (min + max) / 2.0), "mean");
double stdDev = ResourceConfigUtils.getAsDouble(arguments.getOrDefault("std-dev", (max - min) / 6.0), "std-dev");
int maxAttempts = ResourceConfigUtils.getAsInt(arguments.getOrDefault("max-attempts", 128), "max-attempts");
return new GaussianNumberProvider(min, max, mean, stdDev, maxAttempts);
}
}
@Override
public String toString() {
return String.format("GaussianNumberProvider{min=%.2f, max=%.2f, mean=%.2f, stdDev=%.2f, maxAttempts=%d}",
min, max, mean, stdDev, maxAttempts);
}
}

View File

@@ -17,11 +17,13 @@ public class NumberProviders {
public static final Key CONSTANT = Key.of("craftengine:constant");
public static final Key UNIFORM = Key.of("craftengine:uniform");
public static final Key EXPRESSION = Key.of("craftengine:expression");
public static final Key GAUSSIAN = Key.of("craftengine:gaussian");
static {
register(FIXED, FixedNumberProvider.FACTORY);
register(CONSTANT, FixedNumberProvider.FACTORY);
register(UNIFORM, UniformNumberProvider.FACTORY);
register(GAUSSIAN, GaussianNumberProvider.FACTORY);
register(EXPRESSION, ExpressionNumberProvider.FACTORY);
}