mirror of
https://github.com/FatherToast/SpecialMobs.git
synced 2025-06-02 09:16:38 +00:00
Environment-sensitive special chance!
This commit is contained in:
parent
999d9b3edf
commit
74a106ba6a
38 changed files with 520 additions and 170 deletions
|
@ -24,6 +24,7 @@ public class Config {
|
||||||
/** Performs initial loading of all configs in this mod. */
|
/** Performs initial loading of all configs in this mod. */
|
||||||
public static void initialize() {
|
public static void initialize() {
|
||||||
ToastConfigSpec.freezeFileWatcher = true;
|
ToastConfigSpec.freezeFileWatcher = true;
|
||||||
|
ReadMeConfig.makeReadMe( CONFIG_DIR );
|
||||||
MAIN.SPEC.initialize();
|
MAIN.SPEC.initialize();
|
||||||
MobFamily.initBestiary();
|
MobFamily.initBestiary();
|
||||||
ToastConfigSpec.freezeFileWatcher = false;
|
ToastConfigSpec.freezeFileWatcher = false;
|
||||||
|
|
|
@ -15,20 +15,6 @@ public class MainConfig extends Config.AbstractConfig {
|
||||||
super( dir, fileName,
|
super( dir, fileName,
|
||||||
"This config contains options that apply to the mod as a whole, including some master settings",
|
"This config contains options that apply to the mod as a whole, including some master settings",
|
||||||
"toggles for convenience." );
|
"toggles for convenience." );
|
||||||
SPEC.newLine();
|
|
||||||
SPEC.comment(
|
|
||||||
"Terminology used in Special Mobs configs:",
|
|
||||||
" * Mob - An entity that is 'alive', short for \"Mobile\" or MobEntity.",
|
|
||||||
" * Family - The group of mobs based on (but not including) a particular vanilla mob; e.g., Creepers.",
|
|
||||||
" * Species - A specific type of mob within a family; e.g., Fire Creepers or vanilla-replacement Creepers.",
|
|
||||||
" * Vanilla Replacement - The one species within a family that is intended to be a replica of the base vanilla mob.",
|
|
||||||
" * Special Variant - Any species that is not the family's vanilla replacement. Includes species that are",
|
|
||||||
" replicas of 'vanilla special variants'; i.e. Husks and Strays.",
|
|
||||||
" * Mob Replacer - The tool that watches vanilla mob spawns and cancels them to spawn this mod's entities." );
|
|
||||||
SPEC.newLine();
|
|
||||||
SPEC.describeAttributeList();
|
|
||||||
SPEC.newLine();
|
|
||||||
SPEC.describeRegistryEntryList();
|
|
||||||
|
|
||||||
GENERAL = new General( SPEC );
|
GENERAL = new General( SPEC );
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
package fathertoast.specialmobs.common.config;
|
||||||
|
|
||||||
|
import fathertoast.specialmobs.common.config.field.BooleanField;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
public class ReadMeConfig extends Config.AbstractConfig {
|
||||||
|
@SuppressWarnings( "SameParameterValue" )
|
||||||
|
static void makeReadMe( File dir ) { new ReadMeConfig( dir ).SPEC.initialize(); }
|
||||||
|
|
||||||
|
/** Builds the config spec that should be used for this config. */
|
||||||
|
private ReadMeConfig( File dir ) {
|
||||||
|
super( dir, "__README__", "This file contains helpful information about how to use the config files in this mod." );
|
||||||
|
SPEC.newLine( 2 );
|
||||||
|
SPEC.comment(
|
||||||
|
"Terminology used in Special Mobs configs:",
|
||||||
|
" * Mob - An entity that is 'alive', short for \"Mobile\" or MobEntity.",
|
||||||
|
" * Family - The group of mobs based on (but not including) a particular vanilla mob; e.g., Creepers.",
|
||||||
|
" * Species - A specific type of mob within a family; e.g., Fire Creepers or vanilla-replacement Creepers.",
|
||||||
|
" * Vanilla Replacement - The one species within a family that is intended to be a replica of the base vanilla mob.",
|
||||||
|
" * Special Variant - Any species that is not the family's vanilla replacement. Includes species that are",
|
||||||
|
" replicas of 'vanilla special variants'; i.e. Husks and Strays.",
|
||||||
|
" * Mob Replacer - The tool that watches vanilla mob spawns and cancels them to spawn this mod's entities." );
|
||||||
|
SPEC.newLine( 2 );
|
||||||
|
SPEC.describeAttributeList();
|
||||||
|
SPEC.newLine( 2 );
|
||||||
|
SPEC.describeRegistryEntryList();
|
||||||
|
SPEC.newLine( 2 );
|
||||||
|
SPEC.describeEnvironmentListPart1of2();
|
||||||
|
SPEC.newLine();
|
||||||
|
SPEC.describeEnvironmentListPart2of2();
|
||||||
|
|
||||||
|
SPEC.newLine( 4 );
|
||||||
|
SPEC.define( new BooleanField( "secret_mode", false, (String[]) null ) );
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,10 +4,13 @@ import fathertoast.specialmobs.common.bestiary.MobFamily;
|
||||||
import fathertoast.specialmobs.common.config.Config;
|
import fathertoast.specialmobs.common.config.Config;
|
||||||
import fathertoast.specialmobs.common.config.field.BooleanField;
|
import fathertoast.specialmobs.common.config.field.BooleanField;
|
||||||
import fathertoast.specialmobs.common.config.field.DoubleField;
|
import fathertoast.specialmobs.common.config.field.DoubleField;
|
||||||
|
import fathertoast.specialmobs.common.config.field.EnvironmentListField;
|
||||||
import fathertoast.specialmobs.common.config.field.IntField;
|
import fathertoast.specialmobs.common.config.field.IntField;
|
||||||
import fathertoast.specialmobs.common.config.file.ToastConfigSpec;
|
import fathertoast.specialmobs.common.config.file.ToastConfigSpec;
|
||||||
import fathertoast.specialmobs.common.config.file.TomlHelper;
|
import fathertoast.specialmobs.common.config.file.TomlHelper;
|
||||||
import fathertoast.specialmobs.common.config.util.ConfigUtil;
|
import fathertoast.specialmobs.common.config.util.ConfigUtil;
|
||||||
|
import fathertoast.specialmobs.common.config.util.EnvironmentEntry;
|
||||||
|
import fathertoast.specialmobs.common.config.util.EnvironmentList;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -51,7 +54,7 @@ public class FamilyConfig extends Config.AbstractConfig {
|
||||||
|
|
||||||
public final DoubleField familyRandomScaling;
|
public final DoubleField familyRandomScaling;
|
||||||
|
|
||||||
public final DoubleField specialVariantChance;
|
public final DoubleField.EnvironmentSensitive specialVariantChance;
|
||||||
|
|
||||||
public final IntField[] specialVariantWeights;
|
public final IntField[] specialVariantWeights;
|
||||||
|
|
||||||
|
@ -72,9 +75,17 @@ public class FamilyConfig extends Config.AbstractConfig {
|
||||||
|
|
||||||
SPEC.newLine();
|
SPEC.newLine();
|
||||||
|
|
||||||
specialVariantChance = SPEC.define( new DoubleField( "special_variant_chance", variantChance, DoubleField.Range.PERCENT,
|
specialVariantChance = new DoubleField.EnvironmentSensitive(
|
||||||
"The chance for " + family.configName + " to spawn as special variants." ) );
|
SPEC.define( new DoubleField( "special_variant_chance.base", variantChance, DoubleField.Range.PERCENT,
|
||||||
// TODO special variant chance exceptions
|
"The chance for " + family.configName + " to spawn as special variants." ) ),
|
||||||
|
SPEC.define( new EnvironmentListField( "special_variant_chance.exceptions", new EnvironmentList(
|
||||||
|
EnvironmentEntry.builder( (float) variantChance * 0.5F ).beforeDays( 5 ).build(), // Also skips first night's full moon
|
||||||
|
EnvironmentEntry.builder( (float) variantChance * 2.0F ).atMaxMoonLight().aboveDifficulty( 0.5F ).build(),
|
||||||
|
EnvironmentEntry.builder( (float) variantChance * 1.5F ).atMaxMoonLight().build(),
|
||||||
|
EnvironmentEntry.builder( (float) variantChance * 1.5F ).aboveDifficulty( 0.5F ).build() )
|
||||||
|
.setRange( DoubleField.Range.PERCENT ),
|
||||||
|
"The chance for " + family.configName + " to spawn as special variants when specific environmental conditions are met." ) )
|
||||||
|
);
|
||||||
|
|
||||||
SPEC.newLine();
|
SPEC.newLine();
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,12 @@ package fathertoast.specialmobs.common.config.field;
|
||||||
|
|
||||||
import fathertoast.specialmobs.common.config.file.TomlHelper;
|
import fathertoast.specialmobs.common.config.file.TomlHelper;
|
||||||
import fathertoast.specialmobs.common.core.SpecialMobs;
|
import fathertoast.specialmobs.common.core.SpecialMobs;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
|
@ -156,4 +160,89 @@ public class DoubleField extends AbstractConfigField {
|
||||||
return getMin();
|
return getMin();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a double field and an environment exception list, combined into one.
|
||||||
|
* This has convenience methods for returning the value that should be used based on the environment.
|
||||||
|
*/
|
||||||
|
public static class EnvironmentSensitive {
|
||||||
|
/** The base value. */
|
||||||
|
private final DoubleField BASE;
|
||||||
|
/** The environment exceptions list. */
|
||||||
|
private final EnvironmentListField EXCEPTIONS;
|
||||||
|
|
||||||
|
/** Links two fields together as base and exceptions. */
|
||||||
|
public EnvironmentSensitive( DoubleField base, EnvironmentListField exceptions ) {
|
||||||
|
BASE = base;
|
||||||
|
EXCEPTIONS = exceptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return Returns the config field's value. */
|
||||||
|
public double get( World world, @Nullable BlockPos pos ) { return EXCEPTIONS.getOrElse( world, pos, BASE ); }
|
||||||
|
|
||||||
|
/** @return Treats the config field's value as a percent chance (from 0 to 1) and returns the result of a single roll. */
|
||||||
|
public boolean rollChance( Random random, World world, @Nullable BlockPos pos ) { return random.nextDouble() < get( world, pos ); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents an environment sensitive list of weighted values. Unlike the normal weighted list, this is just a simple
|
||||||
|
* wrapper class, and its weights are doubles.
|
||||||
|
* It sacrifices automation for flexibility, largely to help with the craziness of environment list fields.
|
||||||
|
*/
|
||||||
|
public static class EnvironmentSensitiveWeightedList<T> {
|
||||||
|
|
||||||
|
private final List<Entry<T>> UNDERLYING_LIST;
|
||||||
|
|
||||||
|
/** Links an array of values to two arrays of fields as base weights and exceptions. */
|
||||||
|
public EnvironmentSensitiveWeightedList( T[] values, DoubleField[] baseWeights, EnvironmentListField[] weightExceptions ) {
|
||||||
|
if( values.length != baseWeights.length || values.length != weightExceptions.length )
|
||||||
|
throw new IllegalArgumentException( "All arrays must be equal length!" );
|
||||||
|
|
||||||
|
final ArrayList<Entry<T>> list = new ArrayList<>();
|
||||||
|
for( int i = 0; i < values.length; i++ ) {
|
||||||
|
list.add( new Entry<>( values[i], new EnvironmentSensitive( baseWeights[i], weightExceptions[i] ) ) );
|
||||||
|
|
||||||
|
// Do a bit of error checking; allows us to ignore the possibility of negative weights
|
||||||
|
if( baseWeights[i].valueMin < 0.0 || weightExceptions[i].valueDefault.getMinValue() < 0.0 ) {
|
||||||
|
throw new IllegalArgumentException( "Weight is not allowed to be negative! See " +
|
||||||
|
baseWeights[i].getKey() + " and/or " + weightExceptions[i].getKey() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
list.trimToSize();
|
||||||
|
UNDERLYING_LIST = Collections.unmodifiableList( list );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return Returns a random item from this weighted list. Null if none of the items have a positive weight. */
|
||||||
|
@Nullable
|
||||||
|
public T next( Random random, World world, @Nullable BlockPos pos ) {
|
||||||
|
// Due to the 'nebulous' nature of environment-based weights, we must recalculate weights for EVERY call
|
||||||
|
final double[] weights = new double[UNDERLYING_LIST.size()];
|
||||||
|
double targetWeight = 0.0;
|
||||||
|
for( int i = 0; i < weights.length; i++ ) {
|
||||||
|
targetWeight += weights[i] = UNDERLYING_LIST.get( i ).WEIGHT.get( world, pos );
|
||||||
|
}
|
||||||
|
if( targetWeight <= 0.0 ) return null;
|
||||||
|
|
||||||
|
// Now we unravel the target weight to a random point
|
||||||
|
targetWeight *= random.nextDouble();
|
||||||
|
for( int i = 0; i < weights.length; i++ ) {
|
||||||
|
targetWeight -= weights[i];
|
||||||
|
if( targetWeight < 0.0 ) return UNDERLYING_LIST.get( i ).VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
SpecialMobs.LOG.error( "Environment-sensitive weight list was unable to return a value when it should have! " +
|
||||||
|
"This is probably due to error in floating point calculations, perhaps try changing the scale of weights." );
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Entry<T> {
|
||||||
|
final T VALUE;
|
||||||
|
final DoubleField.EnvironmentSensitive WEIGHT;
|
||||||
|
|
||||||
|
Entry( T value, DoubleField.EnvironmentSensitive weight ) {
|
||||||
|
VALUE = value;
|
||||||
|
WEIGHT = weight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -17,6 +17,7 @@ import net.minecraft.world.World;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a config field with an environment list value.
|
* Represents a config field with an environment list value.
|
||||||
|
@ -53,6 +54,7 @@ public class EnvironmentListField extends GenericField<EnvironmentList> {
|
||||||
public static final String ENV_DAY_TIME = "day_time";
|
public static final String ENV_DAY_TIME = "day_time";
|
||||||
public static final String ENV_TIME_FROM_MIDNIGHT = "time_from_midnight";
|
public static final String ENV_TIME_FROM_MIDNIGHT = "time_from_midnight";
|
||||||
public static final String ENV_WORLD_TIME = "world_time";
|
public static final String ENV_WORLD_TIME = "world_time";
|
||||||
|
public static final String ENV_CHUNK_TIME = "chunk_time";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides a description of how to use environment lists. Recommended to put at the top of any file using environment lists.
|
* Provides a description of how to use environment lists. Recommended to put at the top of any file using environment lists.
|
||||||
|
@ -89,7 +91,7 @@ public class EnvironmentListField extends GenericField<EnvironmentList> {
|
||||||
comment.add( " \"" + ENV_TEMPERATURE + " op value\" or \"" + ENV_TEMPERATURE + " (!)" + TemperatureEnvironment.FREEZING + "\":" );
|
comment.add( " \"" + ENV_TEMPERATURE + " op value\" or \"" + ENV_TEMPERATURE + " (!)" + TemperatureEnvironment.FREEZING + "\":" );
|
||||||
comment.add( " Height-adjusted temperature. For reference, freezing is < 0.15 and hot is generally considered > 0.95." );
|
comment.add( " Height-adjusted temperature. For reference, freezing is < 0.15 and hot is generally considered > 0.95." );
|
||||||
comment.add( " \"" + ENV_BIOME_CATEGORY + " (!)category\":" );
|
comment.add( " \"" + ENV_BIOME_CATEGORY + " (!)category\":" );
|
||||||
comment.add( " Valid category values: " + TomlHelper.literalList( (Object[]) BiomeCategoryEnvironment.Value.values() ) );
|
comment.add( " Valid category values: " + TomlHelper.literalList( (Object[]) BiomeCategory.values() ) );
|
||||||
comment.add( " \"" + ENV_BIOME + " (!)namespace:biome_name\":" );
|
comment.add( " \"" + ENV_BIOME + " (!)namespace:biome_name\":" );
|
||||||
comment.add( " The biome. See the wiki for vanilla biome names (resource locations) [https://minecraft.fandom.com/wiki/Biome#Biome_IDs]." );
|
comment.add( " The biome. See the wiki for vanilla biome names (resource locations) [https://minecraft.fandom.com/wiki/Biome#Biome_IDs]." );
|
||||||
// Position-based
|
// Position-based
|
||||||
|
@ -98,7 +100,7 @@ public class EnvironmentListField extends GenericField<EnvironmentList> {
|
||||||
comment.add( " \"" + ENV_Y + " op value\":" );
|
comment.add( " \"" + ENV_Y + " op value\":" );
|
||||||
comment.add( " The y-value. For reference, sea level is normally 63 and lava level is normally 10." );//TODO change lava level to -54 for MC 1.18
|
comment.add( " The y-value. For reference, sea level is normally 63 and lava level is normally 10." );//TODO change lava level to -54 for MC 1.18
|
||||||
comment.add( " \"" + ENV_Y_FROM_SEA + " op value\":" );
|
comment.add( " \"" + ENV_Y_FROM_SEA + " op value\":" );
|
||||||
comment.add( " The y-value from sea level. Expect the only air <= 0 to be in caves (which may still have direct view of the sky)." );
|
comment.add( " The y-value from sea level. Expect the only air <= 0 to be in caves/ravines (which may still have direct view of the sky)." );
|
||||||
comment.add( " \"" + ENV_POSITION + " (!)state\":" );
|
comment.add( " \"" + ENV_POSITION + " (!)state\":" );
|
||||||
comment.add( " Valid state values: " + TomlHelper.literalList( (Object[]) PositionEnvironment.Value.values() ) );
|
comment.add( " Valid state values: " + TomlHelper.literalList( (Object[]) PositionEnvironment.Value.values() ) );
|
||||||
comment.add( " Miscellaneous conditions that generally do what you expect. For reference, 'near' a village is ~3 chunks, and redstone checks weak power." );
|
comment.add( " Miscellaneous conditions that generally do what you expect. For reference, 'near' a village is ~3 chunks, and redstone checks weak power." );
|
||||||
|
@ -123,8 +125,11 @@ public class EnvironmentListField extends GenericField<EnvironmentList> {
|
||||||
comment.add( " The absolute time in ticks away from midnight. Value must be 0 to 12000." );
|
comment.add( " The absolute time in ticks away from midnight. Value must be 0 to 12000." );
|
||||||
comment.add( " \"" + ENV_MOON_PHASE + " (!)phase\":" );
|
comment.add( " \"" + ENV_MOON_PHASE + " (!)phase\":" );
|
||||||
comment.add( " Valid phase values: " + TomlHelper.literalList( (Object[]) MoonPhaseEnvironment.Value.values() ) );
|
comment.add( " Valid phase values: " + TomlHelper.literalList( (Object[]) MoonPhaseEnvironment.Value.values() ) );
|
||||||
|
comment.add( " For reference, the first day in a new world is always a full moon." );
|
||||||
comment.add( " \"" + ENV_WORLD_TIME + " op value\":" );
|
comment.add( " \"" + ENV_WORLD_TIME + " op value\":" );
|
||||||
comment.add( " The total time the world has existed, in ticks. For reference, each day cycle is 24000 ticks and each lunar cycle is 192000 ticks." );
|
comment.add( " The total time the world has existed, in ticks. For reference, each day cycle is 24000 ticks and each lunar cycle is 192000 ticks." );
|
||||||
|
comment.add( " \"" + ENV_CHUNK_TIME + " op value\":" );
|
||||||
|
comment.add( " The total time the chunk has been loaded, in ticks. For reference, each day cycle is 24000 ticks and each lunar cycle is 192000 ticks." );
|
||||||
return comment;
|
return comment;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,7 +172,7 @@ public class EnvironmentListField extends GenericField<EnvironmentList> {
|
||||||
|
|
||||||
final List<AbstractEnvironment> conditions = new ArrayList<>();
|
final List<AbstractEnvironment> conditions = new ArrayList<>();
|
||||||
if( args.length > 1 ) {
|
if( args.length > 1 ) {
|
||||||
final String[] condArgs = args[1].trim().split( "&" );
|
final String[] condArgs = args[1].split( "&" );
|
||||||
for( String condArg : condArgs ) {
|
for( String condArg : condArgs ) {
|
||||||
conditions.add( parseCondition( condArg.trim(), line ) );
|
conditions.add( parseCondition( condArg.trim(), line ) );
|
||||||
}
|
}
|
||||||
|
@ -216,7 +221,7 @@ public class EnvironmentListField extends GenericField<EnvironmentList> {
|
||||||
if( args.length < 2 ) value = "";
|
if( args.length < 2 ) value = "";
|
||||||
else value = args[1].trim();
|
else value = args[1].trim();
|
||||||
|
|
||||||
switch( args[0] ) {
|
switch( args[0].toLowerCase( Locale.ROOT ) ) {
|
||||||
// Dimension-based
|
// Dimension-based
|
||||||
case ENV_DIMENSION_PROPERTY:
|
case ENV_DIMENSION_PROPERTY:
|
||||||
return new DimensionPropertyEnvironment( this, value );
|
return new DimensionPropertyEnvironment( this, value );
|
||||||
|
@ -259,6 +264,8 @@ public class EnvironmentListField extends GenericField<EnvironmentList> {
|
||||||
return new TimeFromMidnightEnvironment( this, value );
|
return new TimeFromMidnightEnvironment( this, value );
|
||||||
case ENV_WORLD_TIME:
|
case ENV_WORLD_TIME:
|
||||||
return new WorldTimeEnvironment( this, value );
|
return new WorldTimeEnvironment( this, value );
|
||||||
|
case ENV_CHUNK_TIME:
|
||||||
|
return new ChunkTimeEnvironment( this, value );
|
||||||
}
|
}
|
||||||
|
|
||||||
// The environment name was not recognized; try to provide some good feedback because this field is complicated
|
// The environment name was not recognized; try to provide some good feedback because this field is complicated
|
||||||
|
@ -271,7 +278,7 @@ public class EnvironmentListField extends GenericField<EnvironmentList> {
|
||||||
ENV_STRUCTURE, ENV_Y, ENV_Y_FROM_SEA, ENV_POSITION,
|
ENV_STRUCTURE, ENV_Y, ENV_Y_FROM_SEA, ENV_POSITION,
|
||||||
// Time-based
|
// Time-based
|
||||||
ENV_DIFFICULTY, ENV_SPECIAL_DIFFICULTY, ENV_WEATHER, ENV_MOON_BRIGHTNESS, ENV_MOON_PHASE, ENV_DAY_TIME,
|
ENV_DIFFICULTY, ENV_SPECIAL_DIFFICULTY, ENV_WEATHER, ENV_MOON_BRIGHTNESS, ENV_MOON_PHASE, ENV_DAY_TIME,
|
||||||
ENV_TIME_FROM_MIDNIGHT, ENV_WORLD_TIME
|
ENV_TIME_FROM_MIDNIGHT, ENV_WORLD_TIME, ENV_CHUNK_TIME
|
||||||
};
|
};
|
||||||
final AbstractEnvironment fallback = new YEnvironment( ComparisonOperator.LESS_THAN, 0 );
|
final AbstractEnvironment fallback = new YEnvironment( ComparisonOperator.LESS_THAN, 0 );
|
||||||
SpecialMobs.LOG.warn( "Invalid environment '{}' for {} \"{}\"! Falling back to \"{}\". Environment name must be in the set [ {} ]. Invalid environment: {}",
|
SpecialMobs.LOG.warn( "Invalid environment '{}' for {} \"{}\"! Falling back to \"{}\". Environment name must be in the set [ {} ]. Invalid environment: {}",
|
||||||
|
|
|
@ -227,6 +227,30 @@ public class ToastConfigSpec {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Represents an appendix header comment. */
|
||||||
|
private static class AppendixHeader extends Format {
|
||||||
|
/** The appendix comment. */
|
||||||
|
private final List<String> COMMENT;
|
||||||
|
|
||||||
|
/** Create a new header action that will insert the opening file comment. */
|
||||||
|
private AppendixHeader( List<String> comment ) {
|
||||||
|
COMMENT = comment;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Called when the config is saved. */
|
||||||
|
@Override
|
||||||
|
public void write( ToastTomlWriter writer, CharacterOutput output ) {
|
||||||
|
writer.decreaseIndentLevel();
|
||||||
|
writer.writeNewLine( output );
|
||||||
|
writer.writeNewLine( output );
|
||||||
|
|
||||||
|
writer.writeComment( "Appendix:", output );
|
||||||
|
writer.writeComment( COMMENT, output );
|
||||||
|
|
||||||
|
writer.increaseIndentLevel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Represents a category comment. */
|
/** Represents a category comment. */
|
||||||
private static class Category extends Format {
|
private static class Category extends Format {
|
||||||
/** The category comment. */
|
/** The category comment. */
|
||||||
|
@ -355,6 +379,9 @@ public class ToastConfigSpec {
|
||||||
/** @param comment The file comment to insert. */
|
/** @param comment The file comment to insert. */
|
||||||
public void header( List<String> comment ) { ACTIONS.add( new Header( this, comment ) ); }
|
public void header( List<String> comment ) { ACTIONS.add( new Header( this, comment ) ); }
|
||||||
|
|
||||||
|
/** @param comment The appendix comment to insert. */
|
||||||
|
public void appendixHeader( String... comment ) { ACTIONS.add( new AppendixHeader( TomlHelper.newComment( comment ) ) ); }
|
||||||
|
|
||||||
/** Inserts a detailed description of how to use the registry entry list field. */
|
/** Inserts a detailed description of how to use the registry entry list field. */
|
||||||
public void describeRegistryEntryList() { ACTIONS.add( new Comment( RegistryEntryListField.verboseDescription() ) ); }
|
public void describeRegistryEntryList() { ACTIONS.add( new Comment( RegistryEntryListField.verboseDescription() ) ); }
|
||||||
|
|
||||||
|
@ -367,6 +394,12 @@ public class ToastConfigSpec {
|
||||||
/** Inserts a detailed description of how to use the block list field. */
|
/** Inserts a detailed description of how to use the block list field. */
|
||||||
public void describeBlockList() { ACTIONS.add( new Comment( BlockListField.verboseDescription() ) ); }
|
public void describeBlockList() { ACTIONS.add( new Comment( BlockListField.verboseDescription() ) ); }
|
||||||
|
|
||||||
|
/** Inserts the first part of a detailed description of how to use the environment list field. Should go with the other field descriptions. */
|
||||||
|
public void describeEnvironmentListPart1of2() { ACTIONS.add( new Comment( EnvironmentListField.verboseDescription() ) ); }
|
||||||
|
|
||||||
|
/** Inserts the second and last part of a detailed description of how to use the environment list field. Should go at the bottom of the file. */
|
||||||
|
public void describeEnvironmentListPart2of2() { ACTIONS.add( new Comment( EnvironmentListField.environmentDescriptions() ) ); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param name The category name.
|
* @param name The category name.
|
||||||
* @param comment The category comment to insert.
|
* @param comment The category comment to insert.
|
||||||
|
|
|
@ -5,6 +5,7 @@ import com.electronwill.nightconfig.core.io.*;
|
||||||
import fathertoast.specialmobs.common.config.field.AbstractConfigField;
|
import fathertoast.specialmobs.common.config.field.AbstractConfigField;
|
||||||
import fathertoast.specialmobs.common.core.SpecialMobs;
|
import fathertoast.specialmobs.common.core.SpecialMobs;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -85,7 +86,7 @@ public class ToastTomlWriter implements ConfigWriter {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Writes a literal array of single-line strings. */
|
/** Writes a literal array of single-line strings. */
|
||||||
public void writeStringArray( List<String> list, CharacterOutput output ) {
|
public void writeStringArray( @Nullable List<String> list, CharacterOutput output ) {
|
||||||
if( list == null || list.isEmpty() ) {
|
if( list == null || list.isEmpty() ) {
|
||||||
writeLine( "[]", output );
|
writeLine( "[]", output );
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -38,8 +38,6 @@ public class SpeciesConfig extends Config.AbstractConfig {
|
||||||
super( FamilyConfig.dir( species.family ), fileName( species ),
|
super( FamilyConfig.dir( species.family ), fileName( species ),
|
||||||
String.format( "This config contains options that apply only to the %s %s species.",
|
String.format( "This config contains options that apply only to the %s %s species.",
|
||||||
variantName( species ), ConfigUtil.camelCaseToLowerSpace( species.family.name ) ) );
|
variantName( species ), ConfigUtil.camelCaseToLowerSpace( species.family.name ) ) );
|
||||||
SPEC.newLine();
|
|
||||||
SPEC.comment( "See the main mod config for common terms and how to use special field types like Attribute List or Registry List." );
|
|
||||||
|
|
||||||
speciesName = variantName( species ) + " " + species.family.configName;
|
speciesName = variantName( species ) + " " + species.family.configName;
|
||||||
|
|
||||||
|
|
|
@ -1,16 +1,20 @@
|
||||||
package fathertoast.specialmobs.common.config.util;
|
package fathertoast.specialmobs.common.config.util;
|
||||||
|
|
||||||
import fathertoast.specialmobs.common.config.util.environment.*;
|
import fathertoast.specialmobs.common.config.util.environment.*;
|
||||||
import fathertoast.specialmobs.common.config.util.environment.biome.BiomeEnvironment;
|
import fathertoast.specialmobs.common.config.util.environment.biome.*;
|
||||||
|
import fathertoast.specialmobs.common.config.util.environment.dimension.DimensionPropertyEnvironment;
|
||||||
import fathertoast.specialmobs.common.config.util.environment.dimension.DimensionTypeEnvironment;
|
import fathertoast.specialmobs.common.config.util.environment.dimension.DimensionTypeEnvironment;
|
||||||
|
import fathertoast.specialmobs.common.config.util.environment.dimension.DimensionTypeGroupEnvironment;
|
||||||
|
import fathertoast.specialmobs.common.config.util.environment.position.PositionEnvironment;
|
||||||
import fathertoast.specialmobs.common.config.util.environment.position.StructureEnvironment;
|
import fathertoast.specialmobs.common.config.util.environment.position.StructureEnvironment;
|
||||||
import fathertoast.specialmobs.common.config.util.environment.position.YEnvironment;
|
import fathertoast.specialmobs.common.config.util.environment.position.YEnvironment;
|
||||||
import fathertoast.specialmobs.common.config.util.environment.position.YFromSeaEnvironment;
|
import fathertoast.specialmobs.common.config.util.environment.position.YFromSeaEnvironment;
|
||||||
|
import fathertoast.specialmobs.common.config.util.environment.time.*;
|
||||||
import net.minecraft.util.RegistryKey;
|
import net.minecraft.util.RegistryKey;
|
||||||
|
import net.minecraft.util.ResourceLocation;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.world.DimensionType;
|
import net.minecraft.world.DimensionType;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
import net.minecraft.world.biome.Biome;
|
|
||||||
import net.minecraft.world.gen.feature.structure.Structure;
|
import net.minecraft.world.gen.feature.structure.Structure;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
@ -64,10 +68,20 @@ public class EnvironmentEntry {
|
||||||
return str.toString();
|
return str.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Builder Implementation
|
||||||
|
|
||||||
|
/** Creates a new entry builder. The value is rounded to 2 decimal place precision. */
|
||||||
|
public static Builder builder( float value ) { return new Builder( Math.round( value * 100.0 ) / 100.0 ); }
|
||||||
|
|
||||||
|
/** Creates a new entry builder. */
|
||||||
public static Builder builder( double value ) { return new Builder( value ); }
|
public static Builder builder( double value ) { return new Builder( value ); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builder class used to simplify creation of environment entries, with shortcuts for the most commonly used environments.
|
* Builder class used to simplify creation of environment entries for default configs,
|
||||||
|
* with shortcuts for the most commonly used environments.
|
||||||
|
* <p>
|
||||||
|
* Keep in mind that ALL conditions in an entry must be satisfied for it to be chosen.
|
||||||
*/
|
*/
|
||||||
public static class Builder {
|
public static class Builder {
|
||||||
private final double VALUE;
|
private final double VALUE;
|
||||||
|
@ -85,28 +99,187 @@ public class EnvironmentEntry {
|
||||||
|
|
||||||
// Dimension-based
|
// Dimension-based
|
||||||
|
|
||||||
public Builder inDimensionType( RegistryKey<DimensionType> dimType ) { return in( new DimensionTypeEnvironment( dimType ) ); }
|
/** Check if the dimension type causes water to instantly vaporize and has faster lava flow. */
|
||||||
|
public Builder inUltraWarmDimension() { return inDimensionWithProperty( DimensionPropertyEnvironment.Value.ULTRAWARM, false ); }
|
||||||
|
|
||||||
|
/** Check if the dimension type causes water to instantly vaporize and has faster lava flow. */
|
||||||
|
public Builder notInUltraWarmDimension() { return inDimensionWithProperty( DimensionPropertyEnvironment.Value.ULTRAWARM, true ); }
|
||||||
|
|
||||||
|
/** Check if the dimension type allows clocks, compasses, and beds to work. */
|
||||||
|
public Builder inNaturalDimension() { return inDimensionWithProperty( DimensionPropertyEnvironment.Value.NATURAL, false ); }
|
||||||
|
|
||||||
|
/** Check if the dimension type allows clocks, compasses, and beds to work. */
|
||||||
|
public Builder notInNaturalDimension() { return inDimensionWithProperty( DimensionPropertyEnvironment.Value.NATURAL, true ); }
|
||||||
|
|
||||||
|
private Builder inDimensionWithProperty( DimensionPropertyEnvironment.Value property, boolean invert ) {
|
||||||
|
return in( new DimensionPropertyEnvironment( property, invert ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder inOverworld() { return inDimensionType( DimensionType.OVERWORLD_LOCATION, false ); }
|
||||||
|
|
||||||
|
public Builder notInOverworld() { return inDimensionType( DimensionType.OVERWORLD_LOCATION, true ); }
|
||||||
|
|
||||||
|
public Builder inNether() { return inDimensionType( DimensionType.NETHER_LOCATION, false ); }
|
||||||
|
|
||||||
|
public Builder notInNether() { return inDimensionType( DimensionType.NETHER_LOCATION, true ); }
|
||||||
|
|
||||||
|
public Builder inTheEnd() { return inDimensionType( DimensionType.END_LOCATION, false ); }
|
||||||
|
|
||||||
|
public Builder notInTheEnd() { return inDimensionType( DimensionType.END_LOCATION, true ); }
|
||||||
|
|
||||||
|
private Builder inDimensionType( RegistryKey<DimensionType> dimType, boolean invert ) { return in( new DimensionTypeEnvironment( dimType, invert ) ); }
|
||||||
|
|
||||||
|
/** Check if the dimension type is vanilla (registered with the "minecraft" namespace). */
|
||||||
|
public Builder inVanillaDimension() { return in( new DimensionTypeGroupEnvironment( new ResourceLocation( "" ), false ) ); }
|
||||||
|
|
||||||
|
/** Check if the dimension type is vanilla (registered with the "minecraft" namespace). */
|
||||||
|
public Builder notInVanillaDimension() { return in( new DimensionTypeGroupEnvironment( new ResourceLocation( "" ), true ) ); }
|
||||||
|
|
||||||
|
|
||||||
// Biome-based
|
// Biome-based
|
||||||
|
|
||||||
public Builder inBiome( RegistryKey<Biome> biome ) { return in( new BiomeEnvironment( biome ) ); }
|
/** Check if the biome has rain disabled. */
|
||||||
|
public Builder inDryBiome() { return inAvgRainfall( ComparisonOperator.EQUAL_TO, 0.0F ); }
|
||||||
|
|
||||||
|
/** Check if the biome has rain disabled. */
|
||||||
|
public Builder notInDryBiome() { return inAvgRainfall( ComparisonOperator.EQUAL_TO.invert(), 0.0F ); }
|
||||||
|
|
||||||
|
/** Check if the biome's humidity hinders fire spread. */
|
||||||
|
public Builder inHumidBiome() { return inAvgRainfall( ComparisonOperator.GREATER_THAN, 0.85F ); }
|
||||||
|
|
||||||
|
/** Check if the biome's humidity hinders fire spread. */
|
||||||
|
public Builder notInHumidBiome() { return inAvgRainfall( ComparisonOperator.GREATER_THAN.invert(), 0.85F ); }
|
||||||
|
|
||||||
|
private Builder inAvgRainfall( ComparisonOperator op, float value ) { return in( new RainfallEnvironment( op, value ) ); }
|
||||||
|
|
||||||
|
/** Check if the temperature is freezing. */
|
||||||
|
public Builder isFreezing() { return in( new TemperatureEnvironment( true ) ); }
|
||||||
|
|
||||||
|
/** Check if the temperature is freezing. */
|
||||||
|
public Builder isNotFreezing() { return in( new TemperatureEnvironment( false ) ); }
|
||||||
|
|
||||||
|
/** Check if the temperature is warm (disables snow golem trails). */
|
||||||
|
public Builder isWarm() { return isTemperature( ComparisonOperator.GREATER_OR_EQUAL, 0.8F ); }
|
||||||
|
|
||||||
|
/** Check if the temperature is warm (disables snow golem trails). */
|
||||||
|
public Builder isNotWarm() { return isTemperature( ComparisonOperator.GREATER_OR_EQUAL.invert(), 0.8F ); }
|
||||||
|
|
||||||
|
/** Check if the temperature is hot (causes snow golems to die). */
|
||||||
|
public Builder isHot() { return isTemperature( ComparisonOperator.GREATER_THAN, 1.0F ); }
|
||||||
|
|
||||||
|
/** Check if the temperature is hot (causes snow golems to die). */
|
||||||
|
public Builder isNotHot() { return isTemperature( ComparisonOperator.GREATER_THAN.invert(), 1.0F ); }
|
||||||
|
|
||||||
|
private Builder isTemperature( ComparisonOperator op, float value ) { return in( new TemperatureEnvironment( op, value ) ); }
|
||||||
|
|
||||||
|
/** Check if the biome belongs to a specific category. */
|
||||||
|
public Builder inBiomeCategory( BiomeCategory category ) { return in( new BiomeCategoryEnvironment( category, false ) ); }
|
||||||
|
|
||||||
|
/** Check if the biome belongs to a specific category. */
|
||||||
|
public Builder notInBiomeCategory( BiomeCategory category ) { return in( new BiomeCategoryEnvironment( category, true ) ); }
|
||||||
|
|
||||||
|
|
||||||
// Position-based
|
// Position-based
|
||||||
|
|
||||||
public Builder inStructure( Structure<?> structure ) { return in( new StructureEnvironment( structure ) ); }
|
/** Check if the position is inside a particular structure. See {@link Structure}. */
|
||||||
|
public Builder inStructure( Structure<?> structure ) { return in( new StructureEnvironment( structure, false ) ); }
|
||||||
|
|
||||||
public Builder belowY( int y ) { return in( new YEnvironment( ComparisonOperator.LESS_THAN, y ) ); }
|
/** Check if the position is inside a particular structure. See {@link Structure}. */
|
||||||
|
public Builder notInStructure( Structure<?> structure ) { return in( new StructureEnvironment( structure, true ) ); }
|
||||||
|
|
||||||
public Builder atLeastY( int y ) { return in( new YEnvironment( ComparisonOperator.GREATER_OR_EQUAL, y ) ); }
|
/** Check if diamond/redstone ore can generate at the position. */
|
||||||
|
public Builder belowDiamondLevel() { return belowY( 15 ); } // TODO update ore-based logic in 1.18
|
||||||
|
|
||||||
public Builder belowSeaLevel() { return in( new YFromSeaEnvironment( ComparisonOperator.LESS_THAN, 0 ) ); }
|
/** Check if diamond/redstone ore can generate at the position. */
|
||||||
|
public Builder aboveDiamondLevel() { return aboveY( 15 ); }
|
||||||
|
|
||||||
public Builder atLeastSeaLevel() { return in( new YFromSeaEnvironment( ComparisonOperator.GREATER_OR_EQUAL, 0 ) ); }
|
/** Check if gold/lapis ore can generate at the position. */
|
||||||
|
public Builder belowGoldLevel() { return belowY( 33 ); }
|
||||||
|
|
||||||
|
/** Check if gold/lapis ore can generate at the position. */
|
||||||
|
public Builder aboveGoldLevel() { return aboveY( 33 ); }
|
||||||
|
|
||||||
|
private Builder belowY( int y ) { return in( new YEnvironment( ComparisonOperator.LESS_OR_EQUAL, y ) ); }
|
||||||
|
|
||||||
|
private Builder aboveY( int y ) { return in( new YEnvironment( ComparisonOperator.LESS_OR_EQUAL.invert(), y ) ); }
|
||||||
|
|
||||||
|
/** Check if the position is above/below sea level. */
|
||||||
|
public Builder belowSeaLevel() { return in( new YFromSeaEnvironment( ComparisonOperator.LESS_OR_EQUAL, 0 ) ); }
|
||||||
|
|
||||||
|
/** Check if the position is above/below sea level. */
|
||||||
|
public Builder aboveSeaLevel() { return in( new YFromSeaEnvironment( ComparisonOperator.LESS_OR_EQUAL.invert(), 0 ) ); }
|
||||||
|
|
||||||
|
/** Check if the position is above/below the average sea floor. */
|
||||||
|
public Builder belowSeaFloor() { return in( new YFromSeaEnvironment( ComparisonOperator.LESS_OR_EQUAL, -18 ) ); }
|
||||||
|
|
||||||
|
/** Check if the position is above/below the average sea floor. */
|
||||||
|
public Builder aboveSeaFloor() { return in( new YFromSeaEnvironment( ComparisonOperator.LESS_OR_EQUAL.invert(), -18 ) ); }
|
||||||
|
|
||||||
|
public Builder canSeeSky() { return inPositionWithState( PositionEnvironment.Value.CAN_SEE_SKY, false ); }
|
||||||
|
|
||||||
|
public Builder cannotSeeSky() { return inPositionWithState( PositionEnvironment.Value.CAN_SEE_SKY, true ); }
|
||||||
|
|
||||||
|
public Builder isNearVillage() { return inPositionWithState( PositionEnvironment.Value.IS_NEAR_VILLAGE, false ); }
|
||||||
|
|
||||||
|
public Builder isNotNearVillage() { return inPositionWithState( PositionEnvironment.Value.IS_NEAR_VILLAGE, true ); }
|
||||||
|
|
||||||
|
public Builder isNearRaid() { return inPositionWithState( PositionEnvironment.Value.IS_NEAR_RAID, false ); }
|
||||||
|
|
||||||
|
public Builder isNotNearRaid() { return inPositionWithState( PositionEnvironment.Value.IS_NEAR_RAID, true ); }
|
||||||
|
|
||||||
|
private Builder inPositionWithState( PositionEnvironment.Value state, boolean invert ) { return in( new PositionEnvironment( state, invert ) ); }
|
||||||
|
|
||||||
|
|
||||||
// Time-based
|
// Time-based
|
||||||
|
|
||||||
|
/** Check if the special difficulty multiplier is above a threshold (0 - 1). */
|
||||||
|
public Builder aboveDifficulty( float percent ) { return in( new SpecialDifficultyEnvironment( ComparisonOperator.GREATER_OR_EQUAL, percent ) ); }
|
||||||
|
|
||||||
|
/** Check if the special difficulty multiplier is above a threshold (0 - 1). */
|
||||||
|
public Builder belowDifficulty( float percent ) { return in( new SpecialDifficultyEnvironment( ComparisonOperator.GREATER_OR_EQUAL.invert(), percent ) ); }
|
||||||
|
|
||||||
|
public Builder isRaining() { return inWeather( WeatherEnvironment.Value.RAIN, false ); } // same as "is not clear"
|
||||||
|
|
||||||
|
public Builder isNotRaining() { return inWeather( WeatherEnvironment.Value.RAIN, true ); } // same as "is clear"
|
||||||
|
|
||||||
|
public Builder isThundering() { return inWeather( WeatherEnvironment.Value.THUNDER, false ); }
|
||||||
|
|
||||||
|
public Builder isNotThundering() { return inWeather( WeatherEnvironment.Value.THUNDER, true ); }
|
||||||
|
|
||||||
|
private Builder inWeather( WeatherEnvironment.Value weather, boolean invert ) { return in( new WeatherEnvironment( weather, invert ) ); }
|
||||||
|
|
||||||
|
public Builder atMaxMoonLight() { return in( new MoonPhaseEnvironment( MoonPhaseEnvironment.Value.FULL, false ) ); }
|
||||||
|
|
||||||
|
public Builder aboveHalfMoonLight() { return fromHalfMoonLight( ComparisonOperator.GREATER_THAN ); }
|
||||||
|
|
||||||
|
public Builder atHalfMoonLight() { return fromHalfMoonLight( ComparisonOperator.EQUAL_TO ); }
|
||||||
|
|
||||||
|
public Builder belowHalfMoonLight() { return fromHalfMoonLight( ComparisonOperator.LESS_THAN ); }
|
||||||
|
|
||||||
|
public Builder atNoMoonLight() { return in( new MoonPhaseEnvironment( MoonPhaseEnvironment.Value.NEW, true ) ); }
|
||||||
|
|
||||||
|
private Builder fromHalfMoonLight( ComparisonOperator op ) { return in( new MoonBrightnessEnvironment( op, 0.5F ) ); }
|
||||||
|
|
||||||
|
public Builder isNight() { return in( new DayTimeEnvironment( DayTimeEnvironment.Value.NIGHT, false ) ); }
|
||||||
|
|
||||||
|
public Builder isDay() { return in( new DayTimeEnvironment( DayTimeEnvironment.Value.DAY, false ) ); }
|
||||||
|
|
||||||
|
/** Check if the time is during a quarter of the night centered on midnight. */
|
||||||
|
public Builder isNearMidnight() { return in( new TimeFromMidnightEnvironment( ComparisonOperator.LESS_OR_EQUAL, 1_500 ) ); }
|
||||||
|
|
||||||
|
/** Check if the time is during a quarter of the night centered on midnight. */
|
||||||
|
public Builder isNotNearMidnight() { return in( new TimeFromMidnightEnvironment( ComparisonOperator.LESS_OR_EQUAL.invert(), 1_500 ) ); }
|
||||||
|
|
||||||
|
/** Check if the world time is after a certain number of days. */
|
||||||
|
public Builder afterDays( int days ) { return in( new WorldTimeEnvironment( ComparisonOperator.GREATER_OR_EQUAL, 24_000L * days ) ); }
|
||||||
|
|
||||||
|
/** Check if the world time is after a certain number of days. */
|
||||||
|
public Builder beforeDays( int days ) { return in( new WorldTimeEnvironment( ComparisonOperator.GREATER_OR_EQUAL.invert(), 24_000L * days ) ); }
|
||||||
|
|
||||||
|
/** Check if the chunk inhabited time is after a certain number of days. */
|
||||||
|
public Builder afterDaysInChunk( int days ) { return in( new ChunkTimeEnvironment( ComparisonOperator.GREATER_OR_EQUAL, 24_000L * days ) ); }
|
||||||
|
|
||||||
|
/** Check if the chunk inhabited time is after a certain number of days. */
|
||||||
|
public Builder beforeDaysInChunk( int days ) { return in( new ChunkTimeEnvironment( ComparisonOperator.GREATER_OR_EQUAL.invert(), 24_000L * days ) ); }
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -15,9 +15,6 @@ import java.util.*;
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings( "unused" )
|
@SuppressWarnings( "unused" )
|
||||||
public class WeightedList<T extends WeightedList.Value> {
|
public class WeightedList<T extends WeightedList.Value> {
|
||||||
/** The spec used by this config that defines the file's format. */
|
|
||||||
protected final ToastConfigSpec SPEC;
|
|
||||||
|
|
||||||
/** The weighted entries in this list. */
|
/** The weighted entries in this list. */
|
||||||
private final List<Entry<T>> ENTRIES;
|
private final List<Entry<T>> ENTRIES;
|
||||||
/** The total weight of all entries in this list. */
|
/** The total weight of all entries in this list. */
|
||||||
|
@ -26,20 +23,20 @@ public class WeightedList<T extends WeightedList.Value> {
|
||||||
/**
|
/**
|
||||||
* Creates a new weighted list config option and registers it and any needed definitions with the spec.
|
* Creates a new weighted list config option and registers it and any needed definitions with the spec.
|
||||||
*/
|
*/
|
||||||
public WeightedList( ToastConfigSpec parent, String key, T[] values, String... description ) {
|
public WeightedList( ToastConfigSpec SPEC, String key, T[] values, @Nullable String... description ) {
|
||||||
this( parent, key, Arrays.asList( values ), description );
|
this( SPEC, key, Arrays.asList( values ), description );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new weighted list config option and registers it and any needed definitions with the spec.
|
* Creates a new weighted list config option and registers it and any needed definitions with the spec.
|
||||||
*/
|
*/
|
||||||
public WeightedList( ToastConfigSpec parent, String key, Iterable<T> values, String... description ) {
|
public WeightedList( ToastConfigSpec SPEC, String key, Iterable<T> values, @Nullable String... description ) {
|
||||||
SPEC = parent;
|
|
||||||
|
|
||||||
final IntField.Range fieldRange = IntField.Range.NON_NEGATIVE;
|
final IntField.Range fieldRange = IntField.Range.NON_NEGATIVE;
|
||||||
|
if( description != null ) {
|
||||||
List<String> comment = TomlHelper.newComment( description );
|
List<String> comment = TomlHelper.newComment( description );
|
||||||
comment.add( TomlHelper.multiFieldInfo( fieldRange ) );
|
comment.add( TomlHelper.multiFieldInfo( fieldRange ) );
|
||||||
SPEC.comment( comment );
|
SPEC.comment( comment );
|
||||||
|
}
|
||||||
|
|
||||||
// Define each value's weight field and connect the value to its weight in an entry
|
// Define each value's weight field and connect the value to its weight in an entry
|
||||||
List<Entry<T>> list = new ArrayList<>();
|
List<Entry<T>> list = new ArrayList<>();
|
||||||
|
|
|
@ -13,56 +13,54 @@ public enum ComparisonOperator {
|
||||||
@Override
|
@Override
|
||||||
public String toString() { return LITERAL; }
|
public String toString() { return LITERAL; }
|
||||||
|
|
||||||
|
/** @return A convenience method that returns the opposite comparison operator only if the passed value is true. */
|
||||||
|
public ComparisonOperator invert( boolean invert ) { return invert ? invert() : this; }
|
||||||
|
|
||||||
|
/** @return The opposite comparison operator. */
|
||||||
|
public ComparisonOperator invert() {
|
||||||
|
switch( this ) {
|
||||||
|
case LESS_THAN: return GREATER_OR_EQUAL;
|
||||||
|
case LESS_OR_EQUAL: return GREATER_THAN;
|
||||||
|
case GREATER_THAN: return LESS_OR_EQUAL;
|
||||||
|
case GREATER_OR_EQUAL: return LESS_THAN;
|
||||||
|
case EQUAL_TO: return NOT_EQUAL_TO;
|
||||||
|
case NOT_EQUAL_TO: return EQUAL_TO;
|
||||||
|
}
|
||||||
|
throw new IllegalStateException( "Inversion implementation is invalid! :(" );
|
||||||
|
}
|
||||||
|
|
||||||
public boolean apply( float first, float second ) {
|
public boolean apply( float first, float second ) {
|
||||||
switch( this ) {
|
switch( this ) {
|
||||||
case LESS_THAN:
|
case LESS_THAN: return first < second;
|
||||||
return first < second;
|
case LESS_OR_EQUAL: return first <= second;
|
||||||
case LESS_OR_EQUAL:
|
case GREATER_THAN: return first > second;
|
||||||
return first <= second;
|
case GREATER_OR_EQUAL: return first >= second;
|
||||||
case GREATER_THAN:
|
case EQUAL_TO: return first == second;
|
||||||
return first > second;
|
case NOT_EQUAL_TO: return first != second;
|
||||||
case GREATER_OR_EQUAL:
|
|
||||||
return first >= second;
|
|
||||||
case EQUAL_TO:
|
|
||||||
return first == second;
|
|
||||||
case NOT_EQUAL_TO:
|
|
||||||
return first != second;
|
|
||||||
}
|
}
|
||||||
throw new IllegalStateException( "Float comparison implementation is invalid! :(" );
|
throw new IllegalStateException( "Float comparison implementation is invalid! :(" );
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean apply( int first, int second ) {
|
public boolean apply( int first, int second ) {
|
||||||
switch( this ) {
|
switch( this ) {
|
||||||
case LESS_THAN:
|
case LESS_THAN: return first < second;
|
||||||
return first < second;
|
case LESS_OR_EQUAL: return first <= second;
|
||||||
case LESS_OR_EQUAL:
|
case GREATER_THAN: return first > second;
|
||||||
return first <= second;
|
case GREATER_OR_EQUAL: return first >= second;
|
||||||
case GREATER_THAN:
|
case EQUAL_TO: return first == second;
|
||||||
return first > second;
|
case NOT_EQUAL_TO: return first != second;
|
||||||
case GREATER_OR_EQUAL:
|
|
||||||
return first >= second;
|
|
||||||
case EQUAL_TO:
|
|
||||||
return first == second;
|
|
||||||
case NOT_EQUAL_TO:
|
|
||||||
return first != second;
|
|
||||||
}
|
}
|
||||||
throw new IllegalStateException( "Integer comparison implementation is invalid! :(" );
|
throw new IllegalStateException( "Integer comparison implementation is invalid! :(" );
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean apply( long first, long second ) {
|
public boolean apply( long first, long second ) {
|
||||||
switch( this ) {
|
switch( this ) {
|
||||||
case LESS_THAN:
|
case LESS_THAN: return first < second;
|
||||||
return first < second;
|
case LESS_OR_EQUAL: return first <= second;
|
||||||
case LESS_OR_EQUAL:
|
case GREATER_THAN: return first > second;
|
||||||
return first <= second;
|
case GREATER_OR_EQUAL: return first >= second;
|
||||||
case GREATER_THAN:
|
case EQUAL_TO: return first == second;
|
||||||
return first > second;
|
case NOT_EQUAL_TO: return first != second;
|
||||||
case GREATER_OR_EQUAL:
|
|
||||||
return first >= second;
|
|
||||||
case EQUAL_TO:
|
|
||||||
return first == second;
|
|
||||||
case NOT_EQUAL_TO:
|
|
||||||
return first != second;
|
|
||||||
}
|
}
|
||||||
throw new IllegalStateException( "Long comparison implementation is invalid! :(" );
|
throw new IllegalStateException( "Long comparison implementation is invalid! :(" );
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,8 +28,6 @@ public abstract class DynamicRegistryEnvironment<T> extends AbstractEnvironment
|
||||||
/** The value of ConfigUtil#DYNAMIC_REGISTRY_VERSION at the time of last poll. */
|
/** The value of ConfigUtil#DYNAMIC_REGISTRY_VERSION at the time of last poll. */
|
||||||
private byte version = -1;
|
private byte version = -1;
|
||||||
|
|
||||||
public DynamicRegistryEnvironment( ResourceLocation regKey ) { this( regKey, false ); }
|
|
||||||
|
|
||||||
public DynamicRegistryEnvironment( ResourceLocation regKey, boolean invert ) {
|
public DynamicRegistryEnvironment( ResourceLocation regKey, boolean invert ) {
|
||||||
FIELD = null;
|
FIELD = null;
|
||||||
INVERT = invert;
|
INVERT = invert;
|
||||||
|
|
|
@ -31,8 +31,6 @@ public abstract class DynamicRegistryGroupEnvironment<T> extends AbstractEnviron
|
||||||
/** The value of ConfigUtil#DYNAMIC_REGISTRY_VERSION at the time of last poll. */
|
/** The value of ConfigUtil#DYNAMIC_REGISTRY_VERSION at the time of last poll. */
|
||||||
private byte version = -1;
|
private byte version = -1;
|
||||||
|
|
||||||
public DynamicRegistryGroupEnvironment( ResourceLocation regKey ) { this( regKey, false ); }
|
|
||||||
|
|
||||||
public DynamicRegistryGroupEnvironment( ResourceLocation regKey, boolean invert ) {
|
public DynamicRegistryGroupEnvironment( ResourceLocation regKey, boolean invert ) {
|
||||||
FIELD = null;
|
FIELD = null;
|
||||||
INVERT = invert;
|
INVERT = invert;
|
||||||
|
|
|
@ -12,8 +12,6 @@ public abstract class EnumEnvironment<T extends Enum<T>> extends AbstractEnviron
|
||||||
/** The enum value for this environment. */
|
/** The enum value for this environment. */
|
||||||
protected final T VALUE;
|
protected final T VALUE;
|
||||||
|
|
||||||
public EnumEnvironment( T value ) { this( value, false ); }
|
|
||||||
|
|
||||||
public EnumEnvironment( T value, boolean invert ) {
|
public EnumEnvironment( T value, boolean invert ) {
|
||||||
INVERT = invert;
|
INVERT = invert;
|
||||||
VALUE = value;
|
VALUE = value;
|
||||||
|
|
|
@ -22,8 +22,6 @@ public abstract class RegistryEnvironment<T extends IForgeRegistryEntry<T>> exte
|
||||||
|
|
||||||
private T registryEntry;
|
private T registryEntry;
|
||||||
|
|
||||||
public RegistryEnvironment( T regEntry ) { this( regEntry, false ); }
|
|
||||||
|
|
||||||
public RegistryEnvironment( T regEntry, boolean invert ) {
|
public RegistryEnvironment( T regEntry, boolean invert ) {
|
||||||
FIELD = null;
|
FIELD = null;
|
||||||
INVERT = invert;
|
INVERT = invert;
|
||||||
|
|
|
@ -24,13 +24,15 @@ public abstract class RegistryGroupEnvironment<T extends IForgeRegistryEntry<T>>
|
||||||
|
|
||||||
private List<T> registryEntries;
|
private List<T> registryEntries;
|
||||||
|
|
||||||
public RegistryGroupEnvironment( T regEntry ) { this( regEntry, false ); }
|
|
||||||
|
|
||||||
public RegistryGroupEnvironment( T regEntry, boolean invert ) {
|
public RegistryGroupEnvironment( T regEntry, boolean invert ) {
|
||||||
|
//noinspection ConstantConditions
|
||||||
|
this( regEntry.getRegistryName(), invert );
|
||||||
|
}
|
||||||
|
|
||||||
|
public RegistryGroupEnvironment( ResourceLocation regKey, boolean invert ) {
|
||||||
FIELD = null;
|
FIELD = null;
|
||||||
INVERT = invert;
|
INVERT = invert;
|
||||||
//noinspection ConstantConditions
|
NAMESPACE = regKey.toString();
|
||||||
NAMESPACE = regEntry.getRegistryName().toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public RegistryGroupEnvironment( AbstractConfigField field, String line ) {
|
public RegistryGroupEnvironment( AbstractConfigField field, String line ) {
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
package fathertoast.specialmobs.common.config.util.environment.biome;
|
||||||
|
|
||||||
|
import net.minecraft.world.biome.Biome;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to wrap the vanilla enum Biome.Category so that it can be safely used in configs.
|
||||||
|
* The declared names should match the string passed into vanilla enums' constructors so that both enums serialize identically.
|
||||||
|
*/
|
||||||
|
public enum BiomeCategory {
|
||||||
|
NONE( Biome.Category.NONE ),
|
||||||
|
TAIGA( Biome.Category.TAIGA ),
|
||||||
|
EXTREME_HILLS( Biome.Category.EXTREME_HILLS ),
|
||||||
|
JUNGLE( Biome.Category.JUNGLE ),
|
||||||
|
MESA( Biome.Category.MESA ),
|
||||||
|
PLAINS( Biome.Category.PLAINS ),
|
||||||
|
SAVANNA( Biome.Category.SAVANNA ),
|
||||||
|
ICY( Biome.Category.ICY ),
|
||||||
|
THE_END( Biome.Category.THEEND ),
|
||||||
|
BEACH( Biome.Category.BEACH ),
|
||||||
|
FOREST( Biome.Category.FOREST ),
|
||||||
|
OCEAN( Biome.Category.OCEAN ),
|
||||||
|
DESERT( Biome.Category.DESERT ),
|
||||||
|
RIVER( Biome.Category.RIVER ),
|
||||||
|
SWAMP( Biome.Category.SWAMP ),
|
||||||
|
MUSHROOM( Biome.Category.MUSHROOM ),
|
||||||
|
NETHER( Biome.Category.NETHER );
|
||||||
|
|
||||||
|
public final Biome.Category BASE;
|
||||||
|
|
||||||
|
BiomeCategory( Biome.Category base ) { BASE = base; }
|
||||||
|
}
|
|
@ -5,40 +5,14 @@ import fathertoast.specialmobs.common.config.field.EnvironmentListField;
|
||||||
import fathertoast.specialmobs.common.config.util.environment.EnumEnvironment;
|
import fathertoast.specialmobs.common.config.util.environment.EnumEnvironment;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
import net.minecraft.world.biome.Biome;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
public class BiomeCategoryEnvironment extends EnumEnvironment<BiomeCategoryEnvironment.Value> {
|
public class BiomeCategoryEnvironment extends EnumEnvironment<BiomeCategory> {
|
||||||
public enum Value {
|
|
||||||
NONE( Biome.Category.NONE ),
|
|
||||||
TAIGA( Biome.Category.TAIGA ),
|
|
||||||
EXTREME_HILLS( Biome.Category.EXTREME_HILLS ),
|
|
||||||
JUNGLE( Biome.Category.JUNGLE ),
|
|
||||||
MESA( Biome.Category.MESA ),
|
|
||||||
PLAINS( Biome.Category.PLAINS ),
|
|
||||||
SAVANNA( Biome.Category.SAVANNA ),
|
|
||||||
ICY( Biome.Category.ICY ),
|
|
||||||
THE_END( Biome.Category.THEEND ),
|
|
||||||
BEACH( Biome.Category.BEACH ),
|
|
||||||
FOREST( Biome.Category.FOREST ),
|
|
||||||
OCEAN( Biome.Category.OCEAN ),
|
|
||||||
DESERT( Biome.Category.DESERT ),
|
|
||||||
RIVER( Biome.Category.RIVER ),
|
|
||||||
SWAMP( Biome.Category.SWAMP ),
|
|
||||||
MUSHROOM( Biome.Category.MUSHROOM ),
|
|
||||||
NETHER( Biome.Category.NETHER );
|
|
||||||
|
|
||||||
public final Biome.Category BASE;
|
public BiomeCategoryEnvironment( BiomeCategory value, boolean invert ) { super( value, invert ); }
|
||||||
|
|
||||||
Value( Biome.Category vanillaCat ) { BASE = vanillaCat; }
|
public BiomeCategoryEnvironment( AbstractConfigField field, String line ) { super( field, line, BiomeCategory.values() ); }
|
||||||
}
|
|
||||||
|
|
||||||
public BiomeCategoryEnvironment( Value value ) { super( value ); }
|
|
||||||
|
|
||||||
public BiomeCategoryEnvironment( Value value, boolean invert ) { super( value, invert ); }
|
|
||||||
|
|
||||||
public BiomeCategoryEnvironment( AbstractConfigField field, String line ) { super( field, line, Value.values() ); }
|
|
||||||
|
|
||||||
/** @return The string name of this environment, as it would appear in a config file. */
|
/** @return The string name of this environment, as it would appear in a config file. */
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -13,8 +13,6 @@ import javax.annotation.Nullable;
|
||||||
|
|
||||||
public class BiomeEnvironment extends DynamicRegistryEnvironment<Biome> {
|
public class BiomeEnvironment extends DynamicRegistryEnvironment<Biome> {
|
||||||
|
|
||||||
public BiomeEnvironment( RegistryKey<Biome> biome ) { super( biome.getRegistryName() ); }
|
|
||||||
|
|
||||||
public BiomeEnvironment( RegistryKey<Biome> biome, boolean invert ) { super( biome.getRegistryName(), invert ); }
|
public BiomeEnvironment( RegistryKey<Biome> biome, boolean invert ) { super( biome.getRegistryName(), invert ); }
|
||||||
|
|
||||||
public BiomeEnvironment( AbstractConfigField field, String line ) { super( field, line ); }
|
public BiomeEnvironment( AbstractConfigField field, String line ) { super( field, line ); }
|
||||||
|
|
|
@ -4,6 +4,7 @@ import fathertoast.specialmobs.common.config.field.AbstractConfigField;
|
||||||
import fathertoast.specialmobs.common.config.field.EnvironmentListField;
|
import fathertoast.specialmobs.common.config.field.EnvironmentListField;
|
||||||
import fathertoast.specialmobs.common.config.util.environment.DynamicRegistryGroupEnvironment;
|
import fathertoast.specialmobs.common.config.util.environment.DynamicRegistryGroupEnvironment;
|
||||||
import net.minecraft.util.RegistryKey;
|
import net.minecraft.util.RegistryKey;
|
||||||
|
import net.minecraft.util.ResourceLocation;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.util.registry.Registry;
|
import net.minecraft.util.registry.Registry;
|
||||||
import net.minecraft.world.biome.Biome;
|
import net.minecraft.world.biome.Biome;
|
||||||
|
@ -14,9 +15,9 @@ import java.util.List;
|
||||||
|
|
||||||
public class BiomeGroupEnvironment extends DynamicRegistryGroupEnvironment<Biome> {
|
public class BiomeGroupEnvironment extends DynamicRegistryGroupEnvironment<Biome> {
|
||||||
|
|
||||||
public BiomeGroupEnvironment( RegistryKey<Biome> biome ) { super( biome.getRegistryName() ); }
|
public BiomeGroupEnvironment( RegistryKey<Biome> biome, boolean invert ) { this( biome.getRegistryName(), invert ); }
|
||||||
|
|
||||||
public BiomeGroupEnvironment( RegistryKey<Biome> biome, boolean invert ) { super( biome.getRegistryName(), invert ); }
|
public BiomeGroupEnvironment( ResourceLocation regKey, boolean invert ) { super( regKey, invert ); }
|
||||||
|
|
||||||
public BiomeGroupEnvironment( AbstractConfigField field, String line ) { super( field, line ); }
|
public BiomeGroupEnvironment( AbstractConfigField field, String line ) { super( field, line ); }
|
||||||
|
|
||||||
|
|
|
@ -2,33 +2,24 @@ package fathertoast.specialmobs.common.config.util.environment.biome;
|
||||||
|
|
||||||
import fathertoast.specialmobs.common.config.field.AbstractConfigField;
|
import fathertoast.specialmobs.common.config.field.AbstractConfigField;
|
||||||
import fathertoast.specialmobs.common.config.field.EnvironmentListField;
|
import fathertoast.specialmobs.common.config.field.EnvironmentListField;
|
||||||
import fathertoast.specialmobs.common.config.util.environment.CompareFloatEnvironment;
|
|
||||||
import fathertoast.specialmobs.common.config.util.environment.ComparisonOperator;
|
import fathertoast.specialmobs.common.config.util.environment.ComparisonOperator;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
public class BiomeTemperatureEnvironment extends CompareFloatEnvironment {
|
public class BiomeTemperatureEnvironment extends TemperatureEnvironment {
|
||||||
|
|
||||||
|
public BiomeTemperatureEnvironment( boolean freezing ) { super( freezing ); }
|
||||||
|
|
||||||
public BiomeTemperatureEnvironment( ComparisonOperator op, float value ) { super( op, value ); }
|
public BiomeTemperatureEnvironment( ComparisonOperator op, float value ) { super( op, value ); }
|
||||||
|
|
||||||
public BiomeTemperatureEnvironment( AbstractConfigField field, String line ) { super( field, TemperatureEnvironment.handleTempInput( line ) ); }
|
public BiomeTemperatureEnvironment( AbstractConfigField field, String line ) { super( field, line ); }
|
||||||
|
|
||||||
/** @return The string name of this environment, as it would appear in a config file. */
|
/** @return The string name of this environment, as it would appear in a config file. */
|
||||||
@Override
|
@Override
|
||||||
public String name() { return EnvironmentListField.ENV_BIOME_TEMPERATURE; }
|
public String name() { return EnvironmentListField.ENV_BIOME_TEMPERATURE; }
|
||||||
|
|
||||||
/** @return The string value of this environment, as it would appear in a config file. */
|
|
||||||
@Override
|
|
||||||
public String value() {
|
|
||||||
if( COMPARATOR == ComparisonOperator.LESS_THAN && VALUE == 0.15F )
|
|
||||||
return TemperatureEnvironment.FREEZING;
|
|
||||||
if( COMPARATOR == ComparisonOperator.GREATER_THAN && VALUE == Math.nextDown( 0.15F ) )
|
|
||||||
return "!" + TemperatureEnvironment.FREEZING;
|
|
||||||
return super.value();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @return Returns the actual value to compare, or Float.NaN if there isn't enough information. */
|
/** @return Returns the actual value to compare, or Float.NaN if there isn't enough information. */
|
||||||
@Override
|
@Override
|
||||||
public float getActual( World world, @Nullable BlockPos pos ) {
|
public float getActual( World world, @Nullable BlockPos pos ) {
|
||||||
|
|
|
@ -12,15 +12,20 @@ import javax.annotation.Nullable;
|
||||||
public class TemperatureEnvironment extends CompareFloatEnvironment {
|
public class TemperatureEnvironment extends CompareFloatEnvironment {
|
||||||
|
|
||||||
public static final String FREEZING = "freezing";
|
public static final String FREEZING = "freezing";
|
||||||
|
public static final float FREEZING_POINT = 0.15F;
|
||||||
|
|
||||||
public static String handleTempInput( String line ) {
|
public static String handleTempInput( String line ) {
|
||||||
if( line.equalsIgnoreCase( FREEZING ) )
|
if( line.equalsIgnoreCase( FREEZING ) )
|
||||||
return ComparisonOperator.LESS_THAN + " " + 0.15F;
|
return ComparisonOperator.LESS_THAN + " " + FREEZING_POINT;
|
||||||
if( line.equalsIgnoreCase( "!" + FREEZING ) )
|
if( line.equalsIgnoreCase( "!" + FREEZING ) )
|
||||||
return ComparisonOperator.GREATER_THAN + " " + Math.nextDown( 0.15F );
|
return ComparisonOperator.LESS_THAN.invert() + " " + FREEZING_POINT;
|
||||||
return line;
|
return line;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TemperatureEnvironment( boolean freezing ) {
|
||||||
|
this( ComparisonOperator.LESS_THAN.invert( !freezing ), FREEZING_POINT );
|
||||||
|
}
|
||||||
|
|
||||||
public TemperatureEnvironment( ComparisonOperator op, float value ) { super( op, value ); }
|
public TemperatureEnvironment( ComparisonOperator op, float value ) { super( op, value ); }
|
||||||
|
|
||||||
public TemperatureEnvironment( AbstractConfigField field, String line ) { super( field, handleTempInput( line ) ); }
|
public TemperatureEnvironment( AbstractConfigField field, String line ) { super( field, handleTempInput( line ) ); }
|
||||||
|
@ -32,10 +37,8 @@ public class TemperatureEnvironment extends CompareFloatEnvironment {
|
||||||
/** @return The string value of this environment, as it would appear in a config file. */
|
/** @return The string value of this environment, as it would appear in a config file. */
|
||||||
@Override
|
@Override
|
||||||
public String value() {
|
public String value() {
|
||||||
if( COMPARATOR == ComparisonOperator.LESS_THAN && VALUE == 0.15F )
|
if( COMPARATOR == ComparisonOperator.LESS_THAN && VALUE == FREEZING_POINT ) return FREEZING;
|
||||||
return FREEZING;
|
if( COMPARATOR == ComparisonOperator.LESS_THAN.invert() && VALUE == FREEZING_POINT ) return "!" + FREEZING;
|
||||||
if( COMPARATOR == ComparisonOperator.GREATER_THAN && VALUE == Math.nextDown( 0.15F ) )
|
|
||||||
return "!" + FREEZING;
|
|
||||||
return super.value();
|
return super.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,8 +35,6 @@ public class DimensionPropertyEnvironment extends EnumEnvironment<DimensionPrope
|
||||||
public boolean of( DimensionType dimType ) { return SUPPLIER.apply( dimType ); }
|
public boolean of( DimensionType dimType ) { return SUPPLIER.apply( dimType ); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public DimensionPropertyEnvironment( Value value ) { super( value ); }
|
|
||||||
|
|
||||||
public DimensionPropertyEnvironment( Value value, boolean invert ) { super( value, invert ); }
|
public DimensionPropertyEnvironment( Value value, boolean invert ) { super( value, invert ); }
|
||||||
|
|
||||||
public DimensionPropertyEnvironment( AbstractConfigField field, String line ) { super( field, line, Value.values() ); }
|
public DimensionPropertyEnvironment( AbstractConfigField field, String line ) { super( field, line, Value.values() ); }
|
||||||
|
|
|
@ -13,8 +13,6 @@ import javax.annotation.Nullable;
|
||||||
|
|
||||||
public class DimensionTypeEnvironment extends DynamicRegistryEnvironment<DimensionType> {
|
public class DimensionTypeEnvironment extends DynamicRegistryEnvironment<DimensionType> {
|
||||||
|
|
||||||
public DimensionTypeEnvironment( RegistryKey<DimensionType> dimType ) { super( dimType.getRegistryName() ); }
|
|
||||||
|
|
||||||
public DimensionTypeEnvironment( RegistryKey<DimensionType> dimType, boolean invert ) { super( dimType.getRegistryName(), invert ); }
|
public DimensionTypeEnvironment( RegistryKey<DimensionType> dimType, boolean invert ) { super( dimType.getRegistryName(), invert ); }
|
||||||
|
|
||||||
public DimensionTypeEnvironment( AbstractConfigField field, String line ) { super( field, line ); }
|
public DimensionTypeEnvironment( AbstractConfigField field, String line ) { super( field, line ); }
|
||||||
|
|
|
@ -4,6 +4,7 @@ import fathertoast.specialmobs.common.config.field.AbstractConfigField;
|
||||||
import fathertoast.specialmobs.common.config.field.EnvironmentListField;
|
import fathertoast.specialmobs.common.config.field.EnvironmentListField;
|
||||||
import fathertoast.specialmobs.common.config.util.environment.DynamicRegistryGroupEnvironment;
|
import fathertoast.specialmobs.common.config.util.environment.DynamicRegistryGroupEnvironment;
|
||||||
import net.minecraft.util.RegistryKey;
|
import net.minecraft.util.RegistryKey;
|
||||||
|
import net.minecraft.util.ResourceLocation;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.util.registry.Registry;
|
import net.minecraft.util.registry.Registry;
|
||||||
import net.minecraft.world.DimensionType;
|
import net.minecraft.world.DimensionType;
|
||||||
|
@ -14,9 +15,9 @@ import java.util.List;
|
||||||
|
|
||||||
public class DimensionTypeGroupEnvironment extends DynamicRegistryGroupEnvironment<DimensionType> {
|
public class DimensionTypeGroupEnvironment extends DynamicRegistryGroupEnvironment<DimensionType> {
|
||||||
|
|
||||||
public DimensionTypeGroupEnvironment( RegistryKey<DimensionType> dimType ) { super( dimType.getRegistryName() ); }
|
public DimensionTypeGroupEnvironment( RegistryKey<DimensionType> dimType, boolean invert ) { this( dimType.getRegistryName(), invert ); }
|
||||||
|
|
||||||
public DimensionTypeGroupEnvironment( RegistryKey<DimensionType> dimType, boolean invert ) { super( dimType.getRegistryName(), invert ); }
|
public DimensionTypeGroupEnvironment( ResourceLocation regKey, boolean invert ) { super( regKey, invert ); }
|
||||||
|
|
||||||
public DimensionTypeGroupEnvironment( AbstractConfigField field, String line ) { super( field, line ); }
|
public DimensionTypeGroupEnvironment( AbstractConfigField field, String line ) { super( field, line ); }
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ public class PositionEnvironment extends EnumEnvironment<PositionEnvironment.Val
|
||||||
IS_IN_VILLAGE( ( world, pos ) -> pos != null && world instanceof ServerWorld && ((ServerWorld) world).isVillage( pos ) ),
|
IS_IN_VILLAGE( ( world, pos ) -> pos != null && world instanceof ServerWorld && ((ServerWorld) world).isVillage( pos ) ),
|
||||||
IS_NEAR_VILLAGE( ( world, pos ) -> pos != null && world instanceof ServerWorld &&
|
IS_NEAR_VILLAGE( ( world, pos ) -> pos != null && world instanceof ServerWorld &&
|
||||||
((ServerWorld) world).isCloseToVillage( pos, 3 ) ),
|
((ServerWorld) world).isCloseToVillage( pos, 3 ) ),
|
||||||
IS_RAIDED( ( world, pos ) -> pos != null && world instanceof ServerWorld && ((ServerWorld) world).isRaided( pos ) ),
|
IS_NEAR_RAID( ( world, pos ) -> pos != null && world instanceof ServerWorld && ((ServerWorld) world).isRaided( pos ) ),
|
||||||
IS_IN_WATER( ( world, pos ) -> pos != null && world.getFluidState( pos ).is( FluidTags.WATER ) ),
|
IS_IN_WATER( ( world, pos ) -> pos != null && world.getFluidState( pos ).is( FluidTags.WATER ) ),
|
||||||
IS_IN_LAVA( ( world, pos ) -> pos != null && world.getFluidState( pos ).is( FluidTags.LAVA ) ),
|
IS_IN_LAVA( ( world, pos ) -> pos != null && world.getFluidState( pos ).is( FluidTags.LAVA ) ),
|
||||||
IS_IN_FLUID( ( world, pos ) -> pos != null && !world.getFluidState( pos ).isEmpty() ),
|
IS_IN_FLUID( ( world, pos ) -> pos != null && !world.getFluidState( pos ).isEmpty() ),
|
||||||
|
@ -31,8 +31,6 @@ public class PositionEnvironment extends EnumEnvironment<PositionEnvironment.Val
|
||||||
public boolean of( World world, @Nullable BlockPos pos ) { return SUPPLIER.apply( world, pos ); }
|
public boolean of( World world, @Nullable BlockPos pos ) { return SUPPLIER.apply( world, pos ); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public PositionEnvironment( Value value ) { super( value ); }
|
|
||||||
|
|
||||||
public PositionEnvironment( Value value, boolean invert ) { super( value, invert ); }
|
public PositionEnvironment( Value value, boolean invert ) { super( value, invert ); }
|
||||||
|
|
||||||
public PositionEnvironment( AbstractConfigField field, String line ) { super( field, line, Value.values() ); }
|
public PositionEnvironment( AbstractConfigField field, String line ) { super( field, line, Value.values() ); }
|
||||||
|
|
|
@ -14,8 +14,6 @@ import javax.annotation.Nullable;
|
||||||
|
|
||||||
public class StructureEnvironment extends RegistryEnvironment<Structure<?>> {
|
public class StructureEnvironment extends RegistryEnvironment<Structure<?>> {
|
||||||
|
|
||||||
public StructureEnvironment( Structure<?> structure ) { super( structure ); }
|
|
||||||
|
|
||||||
public StructureEnvironment( Structure<?> structure, boolean invert ) { super( structure, invert ); }
|
public StructureEnvironment( Structure<?> structure, boolean invert ) { super( structure, invert ); }
|
||||||
|
|
||||||
public StructureEnvironment( AbstractConfigField field, String line ) { super( field, line ); }
|
public StructureEnvironment( AbstractConfigField field, String line ) { super( field, line ); }
|
||||||
|
|
|
@ -3,6 +3,7 @@ package fathertoast.specialmobs.common.config.util.environment.position;
|
||||||
import fathertoast.specialmobs.common.config.field.AbstractConfigField;
|
import fathertoast.specialmobs.common.config.field.AbstractConfigField;
|
||||||
import fathertoast.specialmobs.common.config.field.EnvironmentListField;
|
import fathertoast.specialmobs.common.config.field.EnvironmentListField;
|
||||||
import fathertoast.specialmobs.common.config.util.environment.RegistryGroupEnvironment;
|
import fathertoast.specialmobs.common.config.util.environment.RegistryGroupEnvironment;
|
||||||
|
import net.minecraft.util.ResourceLocation;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
import net.minecraft.world.gen.feature.structure.Structure;
|
import net.minecraft.world.gen.feature.structure.Structure;
|
||||||
|
@ -16,9 +17,9 @@ import java.util.List;
|
||||||
|
|
||||||
public class StructureGroupEnvironment extends RegistryGroupEnvironment<Structure<?>> {
|
public class StructureGroupEnvironment extends RegistryGroupEnvironment<Structure<?>> {
|
||||||
|
|
||||||
public StructureGroupEnvironment( Structure<?> biome ) { super( biome ); }
|
public StructureGroupEnvironment( Structure<?> structure, boolean invert ) { super( structure, invert ); }
|
||||||
|
|
||||||
public StructureGroupEnvironment( Structure<?> biome, boolean invert ) { super( biome, invert ); }
|
public StructureGroupEnvironment( ResourceLocation regKey, boolean invert ) { super( regKey, invert ); }
|
||||||
|
|
||||||
public StructureGroupEnvironment( AbstractConfigField field, String line ) { super( field, line ); }
|
public StructureGroupEnvironment( AbstractConfigField field, String line ) { super( field, line ); }
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
package fathertoast.specialmobs.common.config.util.environment.time;
|
||||||
|
|
||||||
|
import fathertoast.specialmobs.common.config.field.AbstractConfigField;
|
||||||
|
import fathertoast.specialmobs.common.config.field.EnvironmentListField;
|
||||||
|
import fathertoast.specialmobs.common.config.util.environment.CompareLongEnvironment;
|
||||||
|
import fathertoast.specialmobs.common.config.util.environment.ComparisonOperator;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
public class ChunkTimeEnvironment extends CompareLongEnvironment {
|
||||||
|
|
||||||
|
public ChunkTimeEnvironment( ComparisonOperator op, long value ) { super( op, value ); }
|
||||||
|
|
||||||
|
public ChunkTimeEnvironment( AbstractConfigField field, String line ) { super( field, line ); }
|
||||||
|
|
||||||
|
/** @return The minimum value that can be given to the value. */
|
||||||
|
@Override
|
||||||
|
protected long getMinValue() { return 0L; }
|
||||||
|
|
||||||
|
/** @return The string name of this environment, as it would appear in a config file. */
|
||||||
|
@Override
|
||||||
|
public String name() { return EnvironmentListField.ENV_CHUNK_TIME; }
|
||||||
|
|
||||||
|
/** @return Returns the actual value to compare, or null if there isn't enough information. */
|
||||||
|
@Override
|
||||||
|
public Long getActual( World world, @Nullable BlockPos pos ) {
|
||||||
|
// Ignore deprecation; this is intentionally the same method used by World#getCurrentDifficultyAt
|
||||||
|
//noinspection deprecation
|
||||||
|
return pos == null || !world.hasChunkAt( pos ) ? null : world.getChunkAt( pos ).getInhabitedTime();
|
||||||
|
}
|
||||||
|
}
|
|
@ -27,8 +27,6 @@ public class DayTimeEnvironment extends EnumEnvironment<DayTimeEnvironment.Value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public DayTimeEnvironment( Value value ) { super( value ); }
|
|
||||||
|
|
||||||
public DayTimeEnvironment( Value value, boolean invert ) { super( value, invert ); }
|
public DayTimeEnvironment( Value value, boolean invert ) { super( value, invert ); }
|
||||||
|
|
||||||
public DayTimeEnvironment( AbstractConfigField field, String line ) { super( field, line, Value.values() ); }
|
public DayTimeEnvironment( AbstractConfigField field, String line ) { super( field, line, Value.values() ); }
|
||||||
|
|
|
@ -26,8 +26,11 @@ public class DifficultyEnvironment extends CompareFloatEnvironment {
|
||||||
public DifficultyEnvironment( AbstractConfigField field, String line ) { super( field, line ); }
|
public DifficultyEnvironment( AbstractConfigField field, String line ) { super( field, line ); }
|
||||||
|
|
||||||
/** @return The minimum value that can be given to the value. */
|
/** @return The minimum value that can be given to the value. */
|
||||||
|
@Override
|
||||||
protected float getMinValue() { return 0.0F; }
|
protected float getMinValue() { return 0.0F; }
|
||||||
|
|
||||||
|
// Don't specify the max value, just in case a mod changes it.
|
||||||
|
|
||||||
/** @return The string name of this environment, as it would appear in a config file. */
|
/** @return The string name of this environment, as it would appear in a config file. */
|
||||||
@Override
|
@Override
|
||||||
public String name() { return EnvironmentListField.ENV_DIFFICULTY; }
|
public String name() { return EnvironmentListField.ENV_DIFFICULTY; }
|
||||||
|
|
|
@ -17,9 +17,11 @@ public class MoonBrightnessEnvironment extends CompareFloatEnvironment {
|
||||||
public MoonBrightnessEnvironment( AbstractConfigField field, String line ) { super( field, line ); }
|
public MoonBrightnessEnvironment( AbstractConfigField field, String line ) { super( field, line ); }
|
||||||
|
|
||||||
/** @return The minimum value that can be given to the value. */
|
/** @return The minimum value that can be given to the value. */
|
||||||
|
@Override
|
||||||
protected float getMinValue() { return 0.0F; }
|
protected float getMinValue() { return 0.0F; }
|
||||||
|
|
||||||
/** @return The maximum value that can be given to the value. */
|
/** @return The maximum value that can be given to the value. */
|
||||||
|
@Override
|
||||||
protected float getMaxValue() { return 1.0F; }
|
protected float getMaxValue() { return 1.0F; }
|
||||||
|
|
||||||
/** @return The string name of this environment, as it would appear in a config file. */
|
/** @return The string name of this environment, as it would appear in a config file. */
|
||||||
|
|
|
@ -19,8 +19,6 @@ public class MoonPhaseEnvironment extends EnumEnvironment<MoonPhaseEnvironment.V
|
||||||
Value( int i ) { INDEX = i; }
|
Value( int i ) { INDEX = i; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public MoonPhaseEnvironment( Value value ) { super( value ); }
|
|
||||||
|
|
||||||
public MoonPhaseEnvironment( Value value, boolean invert ) { super( value, invert ); }
|
public MoonPhaseEnvironment( Value value, boolean invert ) { super( value, invert ); }
|
||||||
|
|
||||||
public MoonPhaseEnvironment( AbstractConfigField field, String line ) { super( field, line, Value.values() ); }
|
public MoonPhaseEnvironment( AbstractConfigField field, String line ) { super( field, line, Value.values() ); }
|
||||||
|
|
|
@ -23,9 +23,11 @@ public class SpecialDifficultyEnvironment extends CompareFloatEnvironment {
|
||||||
public SpecialDifficultyEnvironment( AbstractConfigField field, String line ) { super( field, line ); }
|
public SpecialDifficultyEnvironment( AbstractConfigField field, String line ) { super( field, line ); }
|
||||||
|
|
||||||
/** @return The minimum value that can be given to the value. */
|
/** @return The minimum value that can be given to the value. */
|
||||||
|
@Override
|
||||||
protected float getMinValue() { return 0.0F; }
|
protected float getMinValue() { return 0.0F; }
|
||||||
|
|
||||||
/** @return The maximum value that can be given to the value. */
|
/** @return The maximum value that can be given to the value. */
|
||||||
|
@Override
|
||||||
protected float getMaxValue() { return 1.0F; }
|
protected float getMaxValue() { return 1.0F; }
|
||||||
|
|
||||||
/** @return The string name of this environment, as it would appear in a config file. */
|
/** @return The string name of this environment, as it would appear in a config file. */
|
||||||
|
|
|
@ -12,15 +12,13 @@ public class WeatherEnvironment extends EnumEnvironment<WeatherEnvironment.Value
|
||||||
/** Values match up to the vanilla weather command. */
|
/** Values match up to the vanilla weather command. */
|
||||||
public enum Value { CLEAR, RAIN, THUNDER }
|
public enum Value { CLEAR, RAIN, THUNDER }
|
||||||
|
|
||||||
public WeatherEnvironment( Value value ) { super( value ); }
|
|
||||||
|
|
||||||
public WeatherEnvironment( Value value, boolean invert ) { super( value, invert ); }
|
public WeatherEnvironment( Value value, boolean invert ) { super( value, invert ); }
|
||||||
|
|
||||||
public WeatherEnvironment( AbstractConfigField field, String line ) { super( field, line, Value.values() ); }
|
public WeatherEnvironment( AbstractConfigField field, String line ) { super( field, line, Value.values() ); }
|
||||||
|
|
||||||
/** @return The string name of this environment, as it would appear in a config file. */
|
/** @return The string name of this environment, as it would appear in a config file. */
|
||||||
@Override
|
@Override
|
||||||
public String name() { return EnvironmentListField.ENV_BIOME_CATEGORY; }
|
public String name() { return EnvironmentListField.ENV_WEATHER; }
|
||||||
|
|
||||||
/** @return Returns true if this environment matches the provided environment. */
|
/** @return Returns true if this environment matches the provided environment. */
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -21,7 +21,7 @@ public class WorldTimeEnvironment extends CompareLongEnvironment {
|
||||||
|
|
||||||
/** @return The string name of this environment, as it would appear in a config file. */
|
/** @return The string name of this environment, as it would appear in a config file. */
|
||||||
@Override
|
@Override
|
||||||
public String name() { return EnvironmentListField.ENV_MOON_BRIGHTNESS; }
|
public String name() { return EnvironmentListField.ENV_WORLD_TIME; }
|
||||||
|
|
||||||
/** @return Returns the actual value to compare, or null if there isn't enough information. */
|
/** @return Returns the actual value to compare, or null if there isn't enough information. */
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -105,7 +105,7 @@ public final class SpecialMobReplacer {
|
||||||
|
|
||||||
/** @return True if the next mob should be made a special variant. */
|
/** @return True if the next mob should be made a special variant. */
|
||||||
private static boolean shouldMakeNextSpecial( MobFamily<?, ?> mobFamily, World world, BlockPos entityPos ) {
|
private static boolean shouldMakeNextSpecial( MobFamily<?, ?> mobFamily, World world, BlockPos entityPos ) {
|
||||||
return world.random.nextFloat() < mobFamily.config.GENERAL.specialVariantChance.get(); //TODO environment exceptions
|
return world.random.nextDouble() < mobFamily.config.GENERAL.specialVariantChance.get( world, entityPos );
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return True if a mob should be replaced. */
|
/** @return True if a mob should be replaced. */
|
||||||
|
|
Loading…
Add table
Reference in a new issue