Skip to content

Commit

Permalink
Refactored Voxelshape logic and made it be sensitive to thickness. Ad…
Browse files Browse the repository at this point in the history
…ded leaf slabs.

Dynamic Trees poisson discs ported.
  • Loading branch information
lilypuree committed Aug 11, 2020
1 parent 63cadfe commit b867af5
Show file tree
Hide file tree
Showing 148 changed files with 4,328 additions and 2,807 deletions.
3 changes: 2 additions & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ modid=forest_tree
mc_version=1.15.2
forge_version=31.2.29
mapping=20200704
jei_version=6.0.0.3
jei_version=6.0.0.3
-Dfile.encoding=UTF-8
11 changes: 11 additions & 0 deletions src/generated/resources/.cache/cache
Original file line number Diff line number Diff line change
@@ -1 +1,12 @@
921fdde87b55bc2e4a892354af04485df58506d2 assets/forest_tree/blockstates/oak_leaves_slab.json
530a07ce720c5647c39d3852e9449d94bc5706cf assets/forest_tree/blockstates/spruce_leaves_slab.json
d6cfc3440ae2f3190da994d2bdfe5c22367426b5 assets/forest_tree/lang/en_us.json
70a2faf623fc5f8acca58c4eff78f8760c032a1d assets/forest_tree/models/block/oak_leaves_slab.json
150f548c6f85d292e7faae8fdd60d91d7a9a3052 assets/forest_tree/models/block/oak_leaves_slabside.json
7a527e40338bfd7e9f1b31e458d153537c1f02c4 assets/forest_tree/models/block/oak_leaves_slabtop.json
6bf5504861df2d2e49c69dbe26f96822557645d2 assets/forest_tree/models/block/spruce_leaves_slab.json
42d56440ce0bee9bdad6ab37fd44c652b0c7ae48 assets/forest_tree/models/block/spruce_leaves_slabside.json
cd6845d6a575cda68028b26639fb8324f57fa844 assets/forest_tree/models/block/spruce_leaves_slabtop.json
dfbb7e2264ed94f9dea4b3befed8d506c509c8d4 assets/forest_tree/models/item/grafting_tool.json
fd84962679dd84d78b20109214123cfd1fe8a4ea assets/forest_tree/models/item/oak_leaves_slab.json
5cd81ad3d2c829d6889d1753c61cdfb240d97327 assets/forest_tree/models/item/spruce_leaves_slab.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
package com.ferreusveritas.dynamictrees.api.worldgen;

import net.minecraft.block.BlockState;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.biome.Biome;

import java.util.ArrayList;
import java.util.Random;

/**
* Provides the forest density for a given biome.
* Mods should implement this interface and register it via the { TreeRegistry} to control how densely populated a {@link Biome} is.
*
* @author ferreusveritas
*/
public class BiomePropertySelectors {

public interface IChanceSelector {
// EnumChance getChance(Random random, @Nonnull Species species, int radius);
}

public interface IDensitySelector {
double getDensity(Random random, double noiseDensity);
}

public interface ISpeciesSelector {
SpeciesSelection getSpecies(BlockPos pos, BlockState dirt, Random random);
}

/**
* This is the data that represents a species selection.
* This class was necessary to have an unhandled state.
*/
public static class SpeciesSelection {
private boolean handled;
// private final Species species;

public SpeciesSelection() {
handled = false;
// species = Species.NULLSPECIES;
}

// public SpeciesSelection(@Nonnull Species species) {
// this.species = species;
// handled = true;
// }

public boolean isHandled() {
return handled;
}

// public Species getSpecies() {
// return species;
// }
}

public static class StaticSpeciesSelector implements ISpeciesSelector {
final SpeciesSelection decision;

public StaticSpeciesSelector(SpeciesSelection decision) {
this.decision = decision;
}

// public StaticSpeciesSelector(@Nonnull Species species) {
// this(new SpeciesSelection(species));
// }

public StaticSpeciesSelector() {
this(new SpeciesSelection());
}

@Override
public SpeciesSelection getSpecies(BlockPos pos, BlockState dirt, Random random) {
return decision;
}
}

public static class RandomSpeciesSelector implements ISpeciesSelector {

private class Entry {
public Entry(SpeciesSelection d, int w) {
decision = d;
weight = w;
}

public SpeciesSelection decision;
public int weight;
}

ArrayList<Entry> decisionTable = new ArrayList<Entry>();
int totalWeight;

public int getSize() {
return decisionTable.size();
}

// public RandomSpeciesSelector add(@Nonnull Species species, int weight) {
// decisionTable.add(new Entry(new SpeciesSelection(species), weight));
// totalWeight += weight;
// return this;
// }

public RandomSpeciesSelector add(int weight) {
decisionTable.add(new Entry(new SpeciesSelection(), weight));
totalWeight += weight;
return this;

}

@Override
public SpeciesSelection getSpecies(BlockPos pos, BlockState dirt, Random random) {
int chance = random.nextInt(totalWeight);

for(Entry entry: decisionTable) {
if(chance < entry.weight) {
return entry.decision;
}
chance -= entry.weight;
};

return decisionTable.get(decisionTable.size() - 1).decision;
}

}


public enum EnumChance {
OK,
CANCEL,
UNHANDLED
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.ferreusveritas.dynamictrees.api.worldgen;

import com.ferreusveritas.dynamictrees.worldgen.BiomeDataBase.BiomeEntry;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IWorld;

public interface IGroundFinder {
BlockPos findGround(BiomeEntry biomeEntry, IWorld world, BlockPos start);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package com.ferreusveritas.dynamictrees.api.worldgen;

import com.ferreusveritas.dynamictrees.systems.poissondisc.PoissonDisc;

import java.util.List;
import java.util.Map;

public interface IPoissonDebug {

void begin(int chunkX, int chunkZ);

void collectSolved(List<PoissonDisc> discs);

void doEdgeMasking(List<PoissonDisc> discs);

void maskSolvedDiscs(List<PoissonDisc> discs);

void createRootDisc(List<PoissonDisc> allDiscs, PoissonDisc rootDisc);

void gatherUnsolved(List<PoissonDisc> unsolvedDiscs, List<PoissonDisc> allDiscs);

void updateCount(int count, List<PoissonDisc> unsolvedDiscs, List<PoissonDisc> allDiscs);

void pickMasterDisc(PoissonDisc master, List<PoissonDisc> unsolvedDiscs, List<PoissonDisc> allDiscs);

void getRadius(PoissonDisc master, int radius, List<PoissonDisc> unsolvedDiscs, List<PoissonDisc> allDiscs);

void findSecondDisc(PoissonDisc master, PoissonDisc slave, List<PoissonDisc> unsolvedDiscs, List<PoissonDisc> allDiscs);

void maskMasterSlave(PoissonDisc master, PoissonDisc slave, List<PoissonDisc> unsolvedDiscs, List<PoissonDisc> allDiscs);

void intersectingList(PoissonDisc slave, Map<Integer, PoissonDisc> intersecting, List<PoissonDisc> allDiscs);

void findThirdDiscCandidate(PoissonDisc master1, PoissonDisc master2, PoissonDisc slave, List<PoissonDisc> unsolvedDiscs, List<PoissonDisc> allDiscs);

void thirdCircleCandidateIntersects(PoissonDisc master1, PoissonDisc master2, PoissonDisc slave, PoissonDisc intersecting, List<PoissonDisc> unsolvedDiscs, List<PoissonDisc> allDiscs);

void findThirdDiscSolved(PoissonDisc slave, List<PoissonDisc> unsolvedDiscs, List<PoissonDisc> allDiscs);

void solveDiscs(List<PoissonDisc> unsolvedDiscs, List<PoissonDisc> allDiscs);

void gatherUnsolved2(List<PoissonDisc> unsolvedDiscs, List<PoissonDisc> allDiscs);

default void unsolvable(int chunkX, int chunkZ, int interations, List<PoissonDisc> unsolvedDiscs, List<PoissonDisc> discs) {
System.err.println("-----" + unsolvedDiscs.size() + " unsolved circles-----");
System.err.println("@ chunk x:" + chunkX + ", z:" + chunkZ);
System.err.println("after " + interations + " iterations" );
for(PoissonDisc c: discs) {
System.err.println((c.hasFreeAngles() ? "->" : " ") + c);
}

//This has been moved to the debugging program
/*if(ModConfigs.poissonDiscImageWrite) {
PoissonDiscDebug.outputCirclesToPng(discs, chunkX, chunkZ, "");
}*/
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.ferreusveritas.dynamictrees.api.worldgen;

import com.ferreusveritas.dynamictrees.systems.poissondisc.PoissonDisc;

import java.util.List;

public interface IPoissonDiscProvider {

List<PoissonDisc> getPoissonDiscs(int chunkX, int chunkY, int chunkZ);

byte[] getChunkPoissonData(int chunkX, int chunkY, int chunkZ);

void setChunkPoissonData(int chunkX, int chunkY, int chunkZ, byte[] circleData);

void unloadChunkPoissonData(int chunkX, int chunkY, int chunkZ);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.ferreusveritas.dynamictrees.api.worldgen;

public interface IRadiusCoordinator {

int getRadiusAtCoords(int x, int z);

boolean runPass(int chunkX, int chunkZ, int pass);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package com.ferreusveritas.dynamictrees.event;

import com.ferreusveritas.dynamictrees.systems.poissondisc.PoissonDiscProviderUniversal;
import com.ferreusveritas.dynamictrees.worldgen.WorldTreeGenerator;
import lilypuree.forest_tree.ForestTree;
import net.minecraft.nbt.ByteArrayNBT;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.IWorld;
import net.minecraftforge.event.world.ChunkDataEvent;
import net.minecraftforge.event.world.WorldEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;

@Mod.EventBusSubscriber(modid = ForestTree.MODID, bus = Mod.EventBusSubscriber.Bus.FORGE)
public class PoissonDiscEventHandler {

/** This piece of crap event will not fire until after PLENTY of chunks have already generated when creating a new world. WHY!? */
/*@SubscribeEvent
public void onWorldLoad(WorldEvent.Load event) {}*/

/**
* We'll use this instead because at least new chunks aren't created after the world is unloaded. I hope. >:(
*/
@SubscribeEvent
public static void onWorldUnload(WorldEvent.Unload event) {
IWorld world = event.getWorld();
if (!world.isRemote()) {
WorldTreeGenerator.getWorldTreeGenerator().getCircleProvider().unloadWorld(world);//clears the circles
}
}


@SubscribeEvent
public static void onChunkDataLoad(ChunkDataEvent.Load event) {
IWorld world = event.getWorld();
if(world != null && !world.isRemote()){
byte circleData[] = event.getData().getByteArray("GTCD");
PoissonDiscProviderUniversal cp = WorldTreeGenerator.getWorldTreeGenerator().getCircleProvider();
cp.setChunkPoissonData(world, event.getChunk().getPos().x, 0, event.getChunk().getPos().z, circleData);
}
}

@SubscribeEvent
public static void onChunkDataSave(ChunkDataEvent.Save event) {
IWorld world = event.getWorld();
ChunkPos chunkPos = event.getChunk().getPos();
PoissonDiscProviderUniversal cp = WorldTreeGenerator.getWorldTreeGenerator().getCircleProvider();
byte circleData[] = cp.getChunkPoissonData(world, chunkPos.x, 0, chunkPos.z);
ByteArrayNBT circleByteArray = new ByteArrayNBT(circleData);
event.getData().put("GTCD", circleByteArray);//Growing Trees Circle Data

// Unload circles here if the chunk is no longer loaded.
if (!world.getChunkProvider().isChunkLoaded(chunkPos)) {
cp.unloadChunkPoissonData(world, chunkPos.x, 0, chunkPos.z);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.ferreusveritas.dynamictrees.event;

import com.ferreusveritas.dynamictrees.api.worldgen.IPoissonDiscProvider;
import net.minecraft.world.IWorld;
import net.minecraft.world.World;
import net.minecraftforge.event.world.WorldEvent;

public class PoissonDiscProviderCreateEvent extends WorldEvent {

private IPoissonDiscProvider poissonDiscProvider;

public PoissonDiscProviderCreateEvent(IWorld world, IPoissonDiscProvider poissonDiscProvider) {
super(world);
this.poissonDiscProvider = poissonDiscProvider;
}

public void setPoissonDiscProvider(IPoissonDiscProvider poissonDiscProvider) {
this.poissonDiscProvider = poissonDiscProvider;
}

public IPoissonDiscProvider getPoissonDiscProvider() {
return poissonDiscProvider;
}

}
Loading

0 comments on commit b867af5

Please sign in to comment.