From 265449c5a75137d80e12e4d21e96853cbb8b6d93 Mon Sep 17 00:00:00 2001 From: dfsek Date: Mon, 1 Mar 2021 16:43:14 -0700 Subject: [PATCH] fix ProbabilityCollection map issues --- common/build.gradle.kts | 2 + .../collections/ProbabilityCollection.java | 42 +++++++++++++---- .../api/world/biome/UserDefinedBiome.java | 7 ++- .../builder/UserDefinedBiomeBuilder.java | 46 +++++++++++-------- .../mutator/BorderListMutatorTemplate.java | 5 +- platforms/bukkit/build.gradle.kts | 2 - 6 files changed, 70 insertions(+), 34 deletions(-) diff --git a/common/build.gradle.kts b/common/build.gradle.kts index fad3faf0c..5938324de 100644 --- a/common/build.gradle.kts +++ b/common/build.gradle.kts @@ -23,6 +23,8 @@ dependencies { "compileOnly"("com.googlecode.json-simple:json-simple:1.1") "compileOnly"("com.google.guava:guava:30.0-jre") + + "testImplementation"("com.google.guava:guava:30.0-jre") } publishing { diff --git a/common/src/main/java/com/dfsek/terra/api/util/collections/ProbabilityCollection.java b/common/src/main/java/com/dfsek/terra/api/util/collections/ProbabilityCollection.java index 9a7ac4032..f9ec64992 100644 --- a/common/src/main/java/com/dfsek/terra/api/util/collections/ProbabilityCollection.java +++ b/common/src/main/java/com/dfsek/terra/api/util/collections/ProbabilityCollection.java @@ -2,25 +2,28 @@ package com.dfsek.terra.api.util.collections; import com.dfsek.terra.api.math.MathUtil; import com.dfsek.terra.api.math.noise.NoiseSampler; +import com.dfsek.terra.api.util.mutable.MutableInteger; import org.jetbrains.annotations.NotNull; import java.util.Collection; import java.util.Collections; +import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; +import java.util.Map; import java.util.Random; import java.util.Set; import java.util.function.Function; @SuppressWarnings("unchecked") public class ProbabilityCollection implements Collection { - private final Set cont = new HashSet<>(); + protected final Map cont = new HashMap<>(); private Object[] array = new Object[0]; private int size; public ProbabilityCollection add(E item, int probability) { - if(!cont.contains(item)) size++; - cont.add(item); + if(!cont.containsKey(item)) size++; + cont.computeIfAbsent(item, i -> new MutableInteger(0)).increment(); int oldLength = array.length; Object[] newArray = new Object[array.length + probability]; System.arraycopy(array, 0, newArray, 0, array.length); // Expand array. @@ -59,6 +62,20 @@ public class ProbabilityCollection implements Collection { 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 public int size() { return size; @@ -71,26 +88,26 @@ public class ProbabilityCollection implements Collection { @Override public boolean contains(Object o) { - return cont.contains(o); + return cont.containsKey(o); } @NotNull @Override public Iterator iterator() { - return cont.iterator(); + return cont.keySet().iterator(); } @NotNull @Override public Object[] toArray() { - return cont.toArray(); + return cont.keySet().toArray(); } @SuppressWarnings("SuspiciousToArrayCall") @NotNull @Override public T[] toArray(@NotNull T[] a) { - return cont.toArray(a); + return cont.keySet().toArray(a); } /** @@ -109,7 +126,7 @@ public class ProbabilityCollection implements Collection { @Override public boolean containsAll(@NotNull Collection c) { - return cont.containsAll(c); + return cont.keySet().containsAll(c); } @Override @@ -135,7 +152,7 @@ public class ProbabilityCollection implements Collection { } public Set getContents() { - return new HashSet<>(cont); + return new HashSet<>(cont.keySet()); } public static final class Singleton extends ProbabilityCollection { @@ -143,6 +160,7 @@ public class ProbabilityCollection implements Collection { public Singleton(T single) { this.single = single; + cont.put(single, new MutableInteger(1)); } @Override @@ -150,6 +168,12 @@ public class ProbabilityCollection implements Collection { throw new UnsupportedOperationException(); } + @Override + public ProbabilityCollection map(Function mapper, boolean carryNull) { + if(carryNull && single == null) return new Singleton<>(null); + return new Singleton<>(mapper.apply(single)); + } + @Override public T get(Random r) { return single; diff --git a/common/src/main/java/com/dfsek/terra/api/world/biome/UserDefinedBiome.java b/common/src/main/java/com/dfsek/terra/api/world/biome/UserDefinedBiome.java index 4425bc70a..b6e5d9570 100644 --- a/common/src/main/java/com/dfsek/terra/api/world/biome/UserDefinedBiome.java +++ b/common/src/main/java/com/dfsek/terra/api/world/biome/UserDefinedBiome.java @@ -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.World; 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.world.generation.WorldGenerator; -import java.util.HashSet; import java.util.Set; /** @@ -65,4 +63,9 @@ public class UserDefinedBiome implements TerraBiome { public Set getTags() { return tags; } + + @Override + public String toString() { + return "{BIOME:" + getID() + "}"; + } } diff --git a/common/src/main/java/com/dfsek/terra/config/builder/UserDefinedBiomeBuilder.java b/common/src/main/java/com/dfsek/terra/config/builder/UserDefinedBiomeBuilder.java index e320b7517..83c458bb5 100644 --- a/common/src/main/java/com/dfsek/terra/config/builder/UserDefinedBiomeBuilder.java +++ b/common/src/main/java/com/dfsek/terra/config/builder/UserDefinedBiomeBuilder.java @@ -16,11 +16,14 @@ import com.dfsek.terra.world.generation.WorldGenerator; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; public class UserDefinedBiomeBuilder implements BiomeBuilder { private final BiomeTemplate template; private final ConfigPack pack; + private final Map biomeMap = new ConcurrentHashMap<>(); + public UserDefinedBiomeBuilder(BiomeTemplate template, ConfigPack pack) { this.template = template; this.pack = pack; @@ -28,29 +31,36 @@ public class UserDefinedBiomeBuilder implements BiomeBuilder { @Override public UserDefinedBiome apply(Long seed) { - NoiseSampler noise; - NoiseSampler elevation; - NoiseSampler carving; - Scope varScope = new Scope().withParent(pack.getVarScope()); + synchronized(biomeMap) { + return biomeMap.computeIfAbsent(seed, + s -> { + 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 noiseBuilderMap = pack.getTemplate().getNoiseBuilderMap(); - Map functionTemplateMap = new HashMap<>(template.getFunctions()); + Map noiseBuilderMap = pack.getTemplate().getNoiseBuilderMap(); + Map functionTemplateMap = new HashMap<>(template.getFunctions()); - functionTemplateMap.putAll(template.getFunctions()); + functionTemplateMap.putAll(template.getFunctions()); - try { - noise = new ExpressionSampler(template.getNoiseEquation(), 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); - } catch(ParseException e) { - throw new RuntimeException(e); + try { + noise = new ExpressionSampler(template.getNoiseEquation(), 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); + } catch(ParseException 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 diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/stage/mutator/BorderListMutatorTemplate.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/stage/mutator/BorderListMutatorTemplate.java index c853ee0a4..9c565621d 100644 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/stage/mutator/BorderListMutatorTemplate.java +++ b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/stage/mutator/BorderListMutatorTemplate.java @@ -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.BorderListMutator; import com.dfsek.terra.config.builder.BiomeBuilder; -import com.dfsek.terra.config.builder.UserDefinedBiomeBuilder; import java.util.HashMap; import java.util.Map; @@ -19,7 +18,7 @@ public class BorderListMutatorTemplate extends MutatorStageTemplate { private String defaultReplace; @Value("default-to") - private ProbabilityCollection defaultTo; + private ProbabilityCollection defaultTo; @Value("replace") private Map> replace; @@ -29,7 +28,7 @@ public class BorderListMutatorTemplate extends MutatorStageTemplate { public BiomeMutator build(long seed) { Map> 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)); } diff --git a/platforms/bukkit/build.gradle.kts b/platforms/bukkit/build.gradle.kts index e3a942319..dbf066f36 100644 --- a/platforms/bukkit/build.gradle.kts +++ b/platforms/bukkit/build.gradle.kts @@ -33,8 +33,6 @@ dependencies { "compileOnly"("com.sk89q.worldedit:worldedit-bukkit:7.2.0-SNAPSHOT") "shadedImplementation"("com.google.guava:guava:30.0-jre") - - "testImplementation"("com.google.guava:guava:30.0-jre") } val testDir = "target/server/"