fix ProbabilityCollection map issues

This commit is contained in:
dfsek
2021-03-01 16:43:14 -07:00
parent 1125b498ec
commit 265449c5a7
6 changed files with 70 additions and 34 deletions
+2
View File
@@ -23,6 +23,8 @@ dependencies {
"compileOnly"("com.googlecode.json-simple:json-simple:1.1") "compileOnly"("com.googlecode.json-simple:json-simple:1.1")
"compileOnly"("com.google.guava:guava:30.0-jre") "compileOnly"("com.google.guava:guava:30.0-jre")
"testImplementation"("com.google.guava:guava:30.0-jre")
} }
publishing { publishing {
@@ -2,25 +2,28 @@ package com.dfsek.terra.api.util.collections;
import com.dfsek.terra.api.math.MathUtil; import com.dfsek.terra.api.math.MathUtil;
import com.dfsek.terra.api.math.noise.NoiseSampler; import com.dfsek.terra.api.math.noise.NoiseSampler;
import com.dfsek.terra.api.util.mutable.MutableInteger;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.Map;
import java.util.Random; import java.util.Random;
import java.util.Set; import java.util.Set;
import java.util.function.Function; import java.util.function.Function;
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public class ProbabilityCollection<E> implements Collection<E> { public class ProbabilityCollection<E> implements Collection<E> {
private final Set<E> cont = new HashSet<>(); protected final Map<E, MutableInteger> cont = new HashMap<>();
private Object[] array = new Object[0]; private Object[] array = new Object[0];
private int size; private int size;
public ProbabilityCollection<E> add(E item, int probability) { public ProbabilityCollection<E> add(E item, int probability) {
if(!cont.contains(item)) size++; if(!cont.containsKey(item)) size++;
cont.add(item); cont.computeIfAbsent(item, i -> new MutableInteger(0)).increment();
int oldLength = array.length; int oldLength = array.length;
Object[] newArray = new Object[array.length + probability]; Object[] newArray = new Object[array.length + probability];
System.arraycopy(array, 0, newArray, 0, array.length); // Expand array. System.arraycopy(array, 0, newArray, 0, array.length); // Expand array.
@@ -59,6 +62,20 @@ public class ProbabilityCollection<E> implements Collection<E> {
return array.length; return array.length;
} }
public int getProbability(E item) {
MutableInteger integer = cont.get(item);
return integer == null ? 0 : integer.get();
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder("[");
cont.forEach((item, prob) -> builder.append(item).append(": ").append(prob).append(", "));
return builder.append("]").toString();
}
@Override @Override
public int size() { public int size() {
return size; return size;
@@ -71,26 +88,26 @@ public class ProbabilityCollection<E> implements Collection<E> {
@Override @Override
public boolean contains(Object o) { public boolean contains(Object o) {
return cont.contains(o); return cont.containsKey(o);
} }
@NotNull @NotNull
@Override @Override
public Iterator<E> iterator() { public Iterator<E> iterator() {
return cont.iterator(); return cont.keySet().iterator();
} }
@NotNull @NotNull
@Override @Override
public Object[] toArray() { public Object[] toArray() {
return cont.toArray(); return cont.keySet().toArray();
} }
@SuppressWarnings("SuspiciousToArrayCall") @SuppressWarnings("SuspiciousToArrayCall")
@NotNull @NotNull
@Override @Override
public <T> T[] toArray(@NotNull T[] a) { public <T> T[] toArray(@NotNull T[] a) {
return cont.toArray(a); return cont.keySet().toArray(a);
} }
/** /**
@@ -109,7 +126,7 @@ public class ProbabilityCollection<E> implements Collection<E> {
@Override @Override
public boolean containsAll(@NotNull Collection<?> c) { public boolean containsAll(@NotNull Collection<?> c) {
return cont.containsAll(c); return cont.keySet().containsAll(c);
} }
@Override @Override
@@ -135,7 +152,7 @@ public class ProbabilityCollection<E> implements Collection<E> {
} }
public Set<E> getContents() { public Set<E> getContents() {
return new HashSet<>(cont); return new HashSet<>(cont.keySet());
} }
public static final class Singleton<T> extends ProbabilityCollection<T> { public static final class Singleton<T> extends ProbabilityCollection<T> {
@@ -143,6 +160,7 @@ public class ProbabilityCollection<E> implements Collection<E> {
public Singleton(T single) { public Singleton(T single) {
this.single = single; this.single = single;
cont.put(single, new MutableInteger(1));
} }
@Override @Override
@@ -150,6 +168,12 @@ public class ProbabilityCollection<E> implements Collection<E> {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@Override
public <T1> ProbabilityCollection<T1> map(Function<T, T1> mapper, boolean carryNull) {
if(carryNull && single == null) return new Singleton<>(null);
return new Singleton<>(mapper.apply(single));
}
@Override @Override
public T get(Random r) { public T get(Random r) {
return single; return single;
@@ -3,11 +3,9 @@ package com.dfsek.terra.api.world.biome;
import com.dfsek.terra.api.platform.world.Biome; import com.dfsek.terra.api.platform.world.Biome;
import com.dfsek.terra.api.platform.world.World; import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.api.util.collections.ProbabilityCollection; import com.dfsek.terra.api.util.collections.ProbabilityCollection;
import com.dfsek.terra.config.builder.GeneratorBuilder;
import com.dfsek.terra.config.templates.BiomeTemplate; import com.dfsek.terra.config.templates.BiomeTemplate;
import com.dfsek.terra.world.generation.WorldGenerator; import com.dfsek.terra.world.generation.WorldGenerator;
import java.util.HashSet;
import java.util.Set; import java.util.Set;
/** /**
@@ -65,4 +63,9 @@ public class UserDefinedBiome implements TerraBiome {
public Set<String> getTags() { public Set<String> getTags() {
return tags; return tags;
} }
@Override
public String toString() {
return "{BIOME:" + getID() + "}";
}
} }
@@ -16,11 +16,14 @@ import com.dfsek.terra.world.generation.WorldGenerator;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class UserDefinedBiomeBuilder implements BiomeBuilder { public class UserDefinedBiomeBuilder implements BiomeBuilder {
private final BiomeTemplate template; private final BiomeTemplate template;
private final ConfigPack pack; private final ConfigPack pack;
private final Map<Long, UserDefinedBiome> biomeMap = new ConcurrentHashMap<>();
public UserDefinedBiomeBuilder(BiomeTemplate template, ConfigPack pack) { public UserDefinedBiomeBuilder(BiomeTemplate template, ConfigPack pack) {
this.template = template; this.template = template;
this.pack = pack; this.pack = pack;
@@ -28,29 +31,36 @@ public class UserDefinedBiomeBuilder implements BiomeBuilder {
@Override @Override
public UserDefinedBiome apply(Long seed) { public UserDefinedBiome apply(Long seed) {
NoiseSampler noise; synchronized(biomeMap) {
NoiseSampler elevation; return biomeMap.computeIfAbsent(seed,
NoiseSampler carving; s -> {
Scope varScope = new Scope().withParent(pack.getVarScope()); NoiseSampler noise;
NoiseSampler elevation;
NoiseSampler carving;
Scope varScope = new Scope().withParent(pack.getVarScope());
template.getVariables().forEach(varScope::create); template.getVariables().forEach(varScope::create);
System.out.println("Building biome " + template.getID() + " for seed " + s);
Map<String, NoiseSeeded> noiseBuilderMap = pack.getTemplate().getNoiseBuilderMap(); Map<String, NoiseSeeded> noiseBuilderMap = pack.getTemplate().getNoiseBuilderMap();
Map<String, FunctionTemplate> functionTemplateMap = new HashMap<>(template.getFunctions()); Map<String, FunctionTemplate> functionTemplateMap = new HashMap<>(template.getFunctions());
functionTemplateMap.putAll(template.getFunctions()); functionTemplateMap.putAll(template.getFunctions());
try { try {
noise = new ExpressionSampler(template.getNoiseEquation(), varScope, seed, noiseBuilderMap, functionTemplateMap); noise = new ExpressionSampler(template.getNoiseEquation(), varScope, seed, noiseBuilderMap, functionTemplateMap);
elevation = template.getElevationEquation() == null ? new ConstantSampler(0) : new ExpressionSampler(template.getElevationEquation(), varScope, seed, noiseBuilderMap, functionTemplateMap); elevation = template.getElevationEquation() == null ? new ConstantSampler(0) : new ExpressionSampler(template.getElevationEquation(), varScope, seed, noiseBuilderMap, functionTemplateMap);
carving = new ExpressionSampler(template.getCarvingEquation(), varScope, seed, noiseBuilderMap, functionTemplateMap); carving = new ExpressionSampler(template.getCarvingEquation(), varScope, seed, noiseBuilderMap, functionTemplateMap);
} catch(ParseException e) { } catch(ParseException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
}
WorldGenerator generator = new WorldGenerator(template.getPalette(), template.getSlantPalette(), noise, elevation, carving, template.getBiomeNoise().apply(seed), template.getElevationWeight(),
template.getBlendDistance(), template.getBlendStep(), template.getBlendWeight());
return new UserDefinedBiome(template.getVanilla(), generator, template);
}
);
} }
WorldGenerator generator = new WorldGenerator(template.getPalette(), template.getSlantPalette(), noise, elevation, carving, template.getBiomeNoise().apply(seed), template.getElevationWeight(),
template.getBlendDistance(), template.getBlendStep(), template.getBlendWeight());
return new UserDefinedBiome(template.getVanilla(), generator, template);
} }
@Override @Override
@@ -6,7 +6,6 @@ import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.api.world.biome.pipeline.mutator.BiomeMutator; import com.dfsek.terra.api.world.biome.pipeline.mutator.BiomeMutator;
import com.dfsek.terra.api.world.biome.pipeline.mutator.BorderListMutator; import com.dfsek.terra.api.world.biome.pipeline.mutator.BorderListMutator;
import com.dfsek.terra.config.builder.BiomeBuilder; import com.dfsek.terra.config.builder.BiomeBuilder;
import com.dfsek.terra.config.builder.UserDefinedBiomeBuilder;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@@ -19,7 +18,7 @@ public class BorderListMutatorTemplate extends MutatorStageTemplate {
private String defaultReplace; private String defaultReplace;
@Value("default-to") @Value("default-to")
private ProbabilityCollection<UserDefinedBiomeBuilder> defaultTo; private ProbabilityCollection<BiomeBuilder> defaultTo;
@Value("replace") @Value("replace")
private Map<BiomeBuilder, ProbabilityCollection<BiomeBuilder>> replace; private Map<BiomeBuilder, ProbabilityCollection<BiomeBuilder>> replace;
@@ -29,7 +28,7 @@ public class BorderListMutatorTemplate extends MutatorStageTemplate {
public BiomeMutator build(long seed) { public BiomeMutator build(long seed) {
Map<TerraBiome, ProbabilityCollection<TerraBiome>> replaceMap = new HashMap<>(); Map<TerraBiome, ProbabilityCollection<TerraBiome>> replaceMap = new HashMap<>();
replace.forEach((biomeBuilder, biomeBuilders) -> replaceMap.put(biomeBuilder.apply(seed), biomeBuilders.map(builder -> builder.apply(seed), true))); replace.forEach((keyBuilder, replacements) -> replaceMap.put(keyBuilder.apply(seed), replacements.map(replacement -> replacement.apply(seed), true)));
return new BorderListMutator(replaceMap, from, defaultReplace, noise.apply(seed), defaultTo.map(biomeBuilder -> biomeBuilder.apply(seed), true)); return new BorderListMutator(replaceMap, from, defaultReplace, noise.apply(seed), defaultTo.map(biomeBuilder -> biomeBuilder.apply(seed), true));
} }
-2
View File
@@ -33,8 +33,6 @@ dependencies {
"compileOnly"("com.sk89q.worldedit:worldedit-bukkit:7.2.0-SNAPSHOT") "compileOnly"("com.sk89q.worldedit:worldedit-bukkit:7.2.0-SNAPSHOT")
"shadedImplementation"("com.google.guava:guava:30.0-jre") "shadedImplementation"("com.google.guava:guava:30.0-jre")
"testImplementation"("com.google.guava:guava:30.0-jre")
} }
val testDir = "target/server/" val testDir = "target/server/"