package mcjty.rftools.items.dimlets; import mcjty.lib.varia.Logging; import mcjty.lib.varia.WeightedRandomSelector; import mcjty.rftools.dimension.description.MobDescriptor; import mcjty.rftools.dimension.world.types.EffectType; import mcjty.rftools.dimension.world.types.FeatureType; import mcjty.rftools.dimension.world.types.StructureType; import net.minecraft.world.World; import net.minecraftforge.common.config.Configuration; import org.apache.commons.lang3.tuple.Pair; import java.util.*; public class DimletRandomizer { public static final int RARITY_0 = 0; public static final int RARITY_1 = 1; public static final int RARITY_2 = 2; public static final int RARITY_3 = 3; public static final int RARITY_4 = 4; public static final int RARITY_5 = 5; public static final int RARITY_6 = 6; public static float rarity0; public static float rarity1; public static float rarity2; public static float rarity3; public static float rarity4; public static float rarity5; public static float rarity6; // Used for randomly generating dimlets. public static final List<DimletKey> dimletIds = new ArrayList<DimletKey>(); static final Map<DimletKey,Integer> dimletBuiltinRarity = new HashMap<DimletKey, Integer>(); // All dimlet ids in a weighted random selector based on rarity. public static WeightedRandomSelector<Integer,DimletKey> randomDimlets; public static WeightedRandomSelector<Integer,DimletKey> randomMaterialDimlets; public static WeightedRandomSelector<Integer,DimletKey> randomLiquidDimlets; public static WeightedRandomSelector<Integer,DimletKey> randomMobDimlets; public static WeightedRandomSelector<Integer,DimletKey> randomStructureDimlets; public static WeightedRandomSelector<Integer,DimletKey> randomEffectDimlets; public static WeightedRandomSelector<Integer,DimletKey> randomFeatureDimlets; public static void clean() { randomDimlets = null; randomMaterialDimlets = null; randomLiquidDimlets = null; randomMobDimlets = null; randomStructureDimlets = null; randomEffectDimlets = null; randomFeatureDimlets = null; } public static void readRandomConfig(Configuration cfg) { rarity0 = (float) cfg.get(KnownDimletConfiguration.CATEGORY_RARITY, "level0", 500.0f).getDouble(); rarity1 = (float) cfg.get(KnownDimletConfiguration.CATEGORY_RARITY, "level1", 250.0f).getDouble(); rarity2 = (float) cfg.get(KnownDimletConfiguration.CATEGORY_RARITY, "level2", 150.0f).getDouble(); rarity3 = (float) cfg.get(KnownDimletConfiguration.CATEGORY_RARITY, "level3", 90.0f).getDouble(); rarity4 = (float) cfg.get(KnownDimletConfiguration.CATEGORY_RARITY, "level4", 40.0f).getDouble(); rarity5 = (float) cfg.get(KnownDimletConfiguration.CATEGORY_RARITY, "level5", 20.0f).getDouble(); rarity6 = (float) cfg.get(KnownDimletConfiguration.CATEGORY_RARITY, "level6", 1.0f).getDouble(); } static void setupWeightedRandomList() { randomDimlets = new WeightedRandomSelector<Integer, DimletKey>(); setupRarity(randomDimlets, rarity0, rarity1, rarity2, rarity3, rarity4, rarity5, rarity6); randomMaterialDimlets = new WeightedRandomSelector<Integer, DimletKey>(); setupRarity(randomMaterialDimlets, rarity0, rarity1, rarity2, rarity3, rarity4, rarity5, rarity6); randomLiquidDimlets = new WeightedRandomSelector<Integer, DimletKey>(); setupRarity(randomLiquidDimlets, rarity0, rarity1, rarity2, rarity3, rarity4, rarity5, rarity6); randomMobDimlets = new WeightedRandomSelector<Integer, DimletKey>(); setupRarity(randomMobDimlets, rarity0, rarity1, rarity2, rarity3, rarity4, rarity5, rarity6); randomStructureDimlets = new WeightedRandomSelector<Integer, DimletKey>(); setupRarity(randomStructureDimlets, rarity0, rarity1, rarity2, rarity3, rarity4, rarity5, rarity6); randomEffectDimlets = new WeightedRandomSelector<Integer, DimletKey>(); setupRarity(randomEffectDimlets, rarity0, rarity1, rarity2, rarity3, rarity4, rarity5, rarity6); randomFeatureDimlets = new WeightedRandomSelector<Integer, DimletKey>(); setupRarity(randomFeatureDimlets, rarity0, rarity1, rarity2, rarity3, rarity4, rarity5, rarity6); for (Map.Entry<DimletKey, DimletEntry> entry : KnownDimletConfiguration.idToDimletEntry.entrySet()) { randomDimlets.addItem(entry.getValue().getRarity(), entry.getKey()); DimletKey key = entry.getValue().getKey(); if (key.getType() == DimletType.DIMLET_MATERIAL) { // Don't add the 'null' material. if (DimletObjectMapping.idToBlock.get(key) != null) { randomMaterialDimlets.addItem(entry.getValue().getRarity(), entry.getKey()); } } else if (key.getType() == DimletType.DIMLET_LIQUID) { // Don't add the 'null' fluid. if (DimletObjectMapping.idToFluid.get(key) != null) { randomLiquidDimlets.addItem(entry.getValue().getRarity(), entry.getKey()); } } else if (key.getType() == DimletType.DIMLET_MOBS) { // Don't add the 'null' mob. MobDescriptor descriptor = DimletObjectMapping.idtoMob.get(key); if (descriptor != null && descriptor.getEntityClass() != null) { randomMobDimlets.addItem(entry.getValue().getRarity(), entry.getKey()); } } else if (key.getType() == DimletType.DIMLET_EFFECT) { // Don't add the 'null' effect. if (DimletObjectMapping.idToEffectType.get(key) != EffectType.EFFECT_NONE) { randomEffectDimlets.addItem(entry.getValue().getRarity(), entry.getKey()); } } else if (key.getType() == DimletType.DIMLET_FEATURE) { // Don't add the 'null' feature. if (DimletObjectMapping.idToFeatureType.get(key) != FeatureType.FEATURE_NONE) { randomFeatureDimlets.addItem(entry.getValue().getRarity(), entry.getKey()); } } else if (key.getType() == DimletType.DIMLET_STRUCTURE) { // Don't add the 'null' structure. if (DimletObjectMapping.idToStructureType.get(key) != StructureType.STRUCTURE_NONE) { randomStructureDimlets.addItem(entry.getValue().getRarity(), entry.getKey()); } } } } private static boolean isDimletNotAllowedForLoot(DimletKey key) { DimletEntry entry = KnownDimletConfiguration.getEntry(key); return entry.isLootNotAllowed(); } private static boolean isDimletNotAllowedForWorldgen(boolean allowRandom, DimletKey key) { return (!allowRandom) && KnownDimletConfiguration.getEntry(key).isRandomNotAllowed(); } public static DimletKey getRandomMob(Random random, boolean allowRandom) { DimletKey key = randomMobDimlets.select(random); while (isDimletNotAllowedForWorldgen(allowRandom, key)) { key = randomMobDimlets.select(random); } return key; } public static DimletKey getRandomEffect(Random random, boolean allowRandom) { DimletKey key = randomEffectDimlets.select(random); while (isDimletNotAllowedForWorldgen(allowRandom, key)) { key = randomEffectDimlets.select(random); } return key; } public static DimletKey getRandomFeature(Random random, boolean allowRandom) { DimletKey key = randomFeatureDimlets.select(random); while (isDimletNotAllowedForWorldgen(allowRandom, key)) { key = randomFeatureDimlets.select(random); } return key; } public static DimletKey getRandomStructure(Random random, boolean allowRandom) { DimletKey key = randomStructureDimlets.select(random); while (isDimletNotAllowedForWorldgen(allowRandom, key)) { key = randomStructureDimlets.select(random); } return key; } public static DimletKey getRandomFluidBlock(Random random, boolean allowRandom) { DimletKey key = randomLiquidDimlets.select(random); while (isDimletNotAllowedForWorldgen(allowRandom, key)) { key = randomLiquidDimlets.select(random); } return key; } public static DimletKey getRandomMaterialBlock(Random random, boolean allowRandom) { DimletKey key = randomMaterialDimlets.select(random); while (isDimletNotAllowedForWorldgen(allowRandom, key)) { key = randomMaterialDimlets.select(random); } return key; } private static void setupRarity(WeightedRandomSelector<Integer,DimletKey> randomDimlets, float rarity0, float rarity1, float rarity2, float rarity3, float rarity4, float rarity5, float rarity6) { randomDimlets.addRarity(RARITY_0, rarity0); randomDimlets.addRarity(RARITY_1, rarity1); randomDimlets.addRarity(RARITY_2, rarity2); randomDimlets.addRarity(RARITY_3, rarity3); randomDimlets.addRarity(RARITY_4, rarity4); randomDimlets.addRarity(RARITY_5, rarity5); randomDimlets.addRarity(RARITY_6, rarity6); } // Get a random dimlet. A bonus of 0.01 will already give a good increase in getting rare items. 0.0 is default. public static DimletKey getRandomDimlet(float bonus, Random random) { WeightedRandomSelector.Distribution<Integer> distribution = randomDimlets.createDistribution(bonus); return getRandomDimlet(distribution, random); } // Get a random dimlet with no bonus. public static DimletKey getRandomDimlet(Random random) { DimletKey key = randomDimlets.select(random); while (isDimletNotAllowedForLoot(key)) { key = randomDimlets.select(random); } return key; } // Get a random dimlet with the given distribution. public static DimletKey getRandomDimlet(WeightedRandomSelector.Distribution<Integer> distribution, Random random) { DimletKey key = randomDimlets.select(distribution, random); while (isDimletNotAllowedForLoot(key)) { key = randomDimlets.select(distribution, random); } return key; } public static void dumpRarityDistribution(float bonus) { Random random = new Random(); Map<DimletKey,Integer> counter = new HashMap<DimletKey, Integer>(); WeightedRandomSelector.Distribution<Integer> distribution = randomDimlets.createDistribution(bonus); DimletMapping mapping = DimletMapping.getInstance(); for (DimletKey key : dimletIds) { counter.put(key, 0); } final int total = 10000000; for (int i = 0 ; i < total ; i++) { DimletKey id = randomDimlets.select(distribution, random); counter.put(id, counter.get(id)+1); } Logging.log("#### Dumping with bonus=" + bonus); List<Pair<Integer,DimletKey>> sortedCounters = new ArrayList<Pair<Integer, DimletKey>>(); for (Map.Entry<DimletKey, Integer> entry : counter.entrySet()) { sortedCounters.add(Pair.of(entry.getValue(), entry.getKey())); } Collections.sort(sortedCounters, new Comparator<Pair<Integer, DimletKey>>() { @Override public int compare(Pair<Integer, DimletKey> o1, Pair<Integer, DimletKey> o2) { return o1.getLeft().compareTo(o2.getLeft()); } }); for (Pair<Integer, DimletKey> entry : sortedCounters) { int count = entry.getKey(); DimletKey key = entry.getValue(); int id = mapping.getId(key); float percentage = count * 100.0f / total; formatDimletOutput(count, key, id, percentage); } } public static void dumpMaterialRarityDistribution(World world) { Random random = new Random(); Map<DimletKey,Integer> counter = new HashMap<DimletKey, Integer>(); for (DimletKey id : DimletObjectMapping.idToBlock.keySet()) { counter.put(id, 0); } DimletMapping mapping = DimletMapping.getDimletMapping(world); final int total = 10000000; for (int i = 0 ; i < total ; i++) { DimletKey key = randomMaterialDimlets.select(random); counter.put(key, counter.get(key)+1); } Logging.log("#### Dumping material distribution"); List<Pair<Integer,DimletKey>> sortedCounters = new ArrayList<Pair<Integer,DimletKey>>(); for (Map.Entry<DimletKey, Integer> entry : counter.entrySet()) { sortedCounters.add(Pair.of(entry.getValue(), entry.getKey())); } Collections.sort(sortedCounters, new Comparator<Pair<Integer, DimletKey>>() { @Override public int compare(Pair<Integer, DimletKey> o1, Pair<Integer, DimletKey> o2) { return o1.getLeft().compareTo(o2.getLeft()); } }); for (Pair<Integer, DimletKey> entry : sortedCounters) { int count = entry.getKey(); DimletKey key = entry.getValue(); int id = mapping.getId(key); float percentage = count * 100.0f / total; formatDimletOutput(count, key, id, percentage); } } private static void formatDimletOutput(int count, DimletKey key, int id, float percentage) { StringBuilder sb = new StringBuilder(); Formatter formatter = new Formatter(sb, Locale.US); String name = KnownDimletConfiguration.idToDisplayName.get(key); DimletEntry de = KnownDimletConfiguration.getEntry(key); int rarity = -1; if (de != null) { rarity = de.getRarity(); } formatter.format("Id:%1$-5d Key:%2$-40.40s Name:%3$-40.40s [Count:%4$-8d %5$g%% R:%6$d]", id, key.toString(), name, count, percentage, rarity); Logging.log(sb.toString()); } }