Skip to content

Commit

Permalink
use a graph cache in tile grapher to prevent repeated computation
Browse files Browse the repository at this point in the history
this works because the growing tile grapher essentially stretches out
the coordinate space of a normal graph, so the same coordinate is
evaluated for multiple in-world coordinates. by preventing repeated
computations, speed is increased by a major degree.
  • Loading branch information
Pixaurora committed Sep 19, 2023
1 parent 1204e3d commit b828a3e
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 83 deletions.
14 changes: 14 additions & 0 deletions src/main/java/net/pixaurora/janerator/graphing/Coordinate.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,15 @@
import java.util.ArrayList;
import java.util.List;

import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction8;
import net.minecraft.world.level.ChunkPos;

public record Coordinate(int x, int z) {
public Coordinate(BlockPos pos) {
this(pos.getX(), pos.getZ());
}

public int toListIndex(int chunkLength) {
return chunkLength * GraphingUtils.mod(this.x, chunkLength) + GraphingUtils.mod(this.z, chunkLength);
}
Expand All @@ -14,6 +20,14 @@ public int toListIndex() {
return this.toListIndex(16);
}

public ChunkPos toChunkPos(int chunkLength) {
return new ChunkPos(Math.floorDiv(this.x, chunkLength), Math.floorDiv(this.z, chunkLength));
}

public ChunkPos toChunkPos() {
return this.toChunkPos(16);
}

public static Coordinate fromListIndex(int index, int chunkLength) {
return new Coordinate(Math.floorDiv(index, chunkLength), GraphingUtils.mod(index, chunkLength));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ public static GraphedChunk allUnshaded(ChunkGrapher grapher, ChunkPos pos) {
);
}

public boolean isShaded(Coordinate pos) {
return this.shading.get(pos.toListIndex());
}

private List<ChunkGenerator> getBlockScaleMap(MultiGenerator multiGenerator) {
List<ChunkGenerator> generatorMap = new ArrayList<>(
IntStream.range(0, 256)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package net.pixaurora.janerator.graphing.grapher;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;

import net.minecraft.world.level.ChunkPos;
import net.pixaurora.janerator.graphing.GraphedChunk;

public abstract class CachingGrapher implements ChunkGrapher {
private LoadingCache<ChunkPos, GraphedChunk> cache;

public CachingGrapher() {
this.cache = CacheBuilder.newBuilder()
.expireAfterAccess(60, TimeUnit.SECONDS)
.maximumSize(1024)
.build(CacheLoader.from(chunk -> new GraphedChunk(this, chunk)));
}

@Override
public GraphedChunk getChunkGraph(ChunkPos chunk) {
try {
return this.cache.get(chunk);
} catch (ExecutionException e) {
throw new RuntimeException(e);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,57 +1,26 @@
package net.pixaurora.janerator.graphing.grapher;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.mojang.serialization.Codec;

import net.minecraft.core.BlockPos;
import net.minecraft.world.level.ChunkPos;
import net.pixaurora.janerator.graphing.Coordinate;
import net.pixaurora.janerator.graphing.GraphedChunk;
import net.pixaurora.janerator.graphing.GraphingUtils;

public abstract class ChunkGrapher {
public interface ChunkGrapher {
public static Codec<ChunkGrapher> CODEC = GrapherType.CODEC.dispatch("type", ChunkGrapher::type, GrapherType::getAppliedCodec);

private LoadingCache<ChunkPos, GraphedChunk> cache;

public ChunkGrapher() {
this.cache = CacheBuilder.newBuilder()
.expireAfterWrite(60, TimeUnit.SECONDS)
.maximumSize(1024)
.build(CacheLoader.from(this::graphChunk));
}
public GrapherType type();

public abstract boolean isPointShaded(int x, int z);
public GraphedChunk getChunkGraph(ChunkPos pos);

public abstract GrapherType type();

public boolean isPointShaded(Coordinate coord) {
return this.isPointShaded(coord.x(), coord.z());
}

public boolean isPointShaded(BlockPos pos) {
return this.isPointShaded(pos.getX(), pos.getZ());
}

private GraphedChunk graphChunk(ChunkPos pos) {
return new GraphedChunk(this, pos);
}
public boolean isPointShaded(Coordinate pos);

public GraphedChunk getChunkGraph(ChunkPos pos) {
try {
return this.cache.get(pos);
} catch (ExecutionException e) {
throw new RuntimeException(e);
}
public default boolean isPointShaded(int x, int z) {
return this.isPointShaded(new Coordinate(x, z));
}

public CompletableFuture<GraphedChunk> scheduleChunkGraphing(ChunkPos pos) {
return CompletableFuture.supplyAsync(() -> this.getChunkGraph(pos), GraphingUtils.threadPool);
public default boolean isPointShaded(BlockPos pos) {
return this.isPointShaded(new Coordinate(pos));
}
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
package net.pixaurora.janerator.graphing.grapher;

import java.util.ArrayList;
import java.util.List;

import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;

import net.pixaurora.janerator.graphing.Coordinate;
import net.pixaurora.janerator.graphing.GraphFunction;
import net.pixaurora.janerator.graphing.GraphFunctionDefinition;
import net.pixaurora.janerator.graphing.instruction.Instruction;

public class CustomGrapher extends ChunkGrapher {
public class CustomGrapher extends CachingGrapher {
public static final Codec<CustomGrapher> CODEC = RecordCodecBuilder.create(
instance -> instance.group(
GraphFunctionDefinition.BIVARIATE_CODEC.fieldOf("graph(x, z)").forGetter(CustomGrapher::getGraphDefinition)
Expand All @@ -21,47 +18,21 @@ public class CustomGrapher extends ChunkGrapher {
protected ThreadLocal<GraphFunction> graphFunction;

public CustomGrapher(GraphFunctionDefinition graphDefinition) {
super();

this.graphDefinition = graphDefinition;
this.graphFunction = ThreadLocal.withInitial(() -> GraphFunction.fromDefinition(this.graphDefinition));
}

public GraphFunctionDefinition getGraphDefinition() {
return this.graphDefinition;
}

@Override
public boolean isPointShaded(int x, int z) {
return this.graphFunction.get().evaluate(x, z) == 1.0;
public boolean isPointShaded(Coordinate pos) {
return this.graphFunction.get().evaluate(pos.x(), pos.z()) == 1.0;
}

@Override
public GrapherType type() {
return GrapherType.CUSTOM;
}

public GraphFunctionDefinition getGraphDefinition() {
return graphDefinition;
}

public static class LocalGrapher {
private List<Double> startingVariables;
private List<Instruction> appliedSteps;
private int returnIndex;

public LocalGrapher(List<Double> startingVariables, List<Instruction> appliedSteps, int returnIndex) {
this.startingVariables = startingVariables;
this.appliedSteps = appliedSteps;
this.returnIndex = returnIndex;
}

public boolean isShaded(double x, double z) {
List<Double> variables = new ArrayList<>(this.startingVariables);
variables.set(0, x);
variables.set(1, z);

for (Instruction step : this.appliedSteps) {
step.execute(variables);
}

return variables.get(this.returnIndex) == 1.0;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,31 @@
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;

import net.minecraft.core.BlockPos;
import net.minecraft.world.level.ChunkPos;
import net.pixaurora.janerator.graphing.Coordinate;
import net.pixaurora.janerator.graphing.GraphFunction;
import net.pixaurora.janerator.graphing.GraphFunctionDefinition;
import net.pixaurora.janerator.graphing.GraphedChunk;
import net.pixaurora.janerator.graphing.grapher.tile.TileData;

public class GrowingTileGrapher extends CustomGrapher {
public class GrowingTileGrapher implements ChunkGrapher {
public static final Codec<GrowingTileGrapher> CODEC = RecordCodecBuilder.create(
instance -> instance.group(
GraphFunctionDefinition.BIVARIATE_CODEC.fieldOf("graph(x, z)").forGetter(GrowingTileGrapher::getTileDefinition),
GraphFunctionDefinition.UNIVARIATE_CODEC.fieldOf("tileSize(v)").forGetter(GrowingTileGrapher::getGraphDefinition)
GraphFunctionDefinition.UNIVARIATE_CODEC.fieldOf("tile_size(v)").forGetter(GrowingTileGrapher::getGraphDefinition)
).apply(instance, GrowingTileGrapher::new)
);

public static final int MAX_VALUE = (int) Math.pow(2, 25);

private CustomGrapher stretchedGrapher;

private GraphFunctionDefinition tileDefinition;
private List<Integer> tileSums;

public GrowingTileGrapher(GraphFunctionDefinition graphDefinition, GraphFunctionDefinition tileGrowthDefinition) {
super(graphDefinition);
this.stretchedGrapher = new CustomGrapher(graphDefinition);
this.tileDefinition = tileGrowthDefinition;

this.tileSums = new ArrayList<>();
Expand All @@ -45,6 +51,10 @@ public GrowingTileGrapher(GraphFunctionDefinition graphDefinition, GraphFunction
}
}

public GraphFunctionDefinition getGraphDefinition() {
return this.stretchedGrapher.getGraphDefinition();
}

public GraphFunctionDefinition getTileDefinition() {
return this.tileDefinition;
}
Expand All @@ -67,12 +77,25 @@ public TileData convertToTile(int realPosition) {
throw new RuntimeException(String.format("Value %d is above the limit of stored values %d!", realPosition, MAX_VALUE));
}

private boolean isTileShaded(Coordinate tilePos) {
GraphedChunk graph = this.stretchedGrapher.getChunkGraph(new ChunkPos(new BlockPos(tilePos.x(), 0, tilePos.z())));

return graph.isShaded(tilePos.makeLegal());
}

@Override
public boolean isPointShaded(int x, int z) {
TileData tileX = this.convertToTile(x);
TileData tileZ = this.convertToTile(z);
public boolean isPointShaded(Coordinate pos) {
TileData tileX = this.convertToTile(pos.x());
TileData tileZ = this.convertToTile(pos.z());

Coordinate tilePos = new Coordinate(tileX.pos(), tileZ.pos());

return this.graphFunction.get().evaluate(tileX.pos(), tileZ.pos()) == 1.0;
return this.isTileShaded(tilePos);
}

@Override
public GraphedChunk getChunkGraph(ChunkPos chunk) {
return new GraphedChunk(this, chunk);
}

@Override
Expand Down

0 comments on commit b828a3e

Please sign in to comment.