Skip to content

Commit

Permalink
Merge pull request #13 from konstructs/feature-add-leaf-decay
Browse files Browse the repository at this point in the history
Add support for leaf decay
  • Loading branch information
petterarvidsson committed May 25, 2016
2 parents 23d66e1 + 24d1be9 commit 9e3d49d
Show file tree
Hide file tree
Showing 5 changed files with 164 additions and 5 deletions.
9 changes: 7 additions & 2 deletions src/main/java/org/konstructs/forest/ForestConfig.java
Expand Up @@ -22,6 +22,7 @@ public class ForestConfig {
private final int maxSeedsPerGeneration;
private final int seedEveryGeneration;
private final int randomGrowth;
private final int leafDecayDelay;

ForestConfig(String wood,
String leaves,
Expand All @@ -41,7 +42,8 @@ public class ForestConfig {
int randomGrowthDelay,
int maxSeedsPerGeneration,
int seedEveryGeneration,
int randomGrowth) {
int randomGrowth,
int leafDecayDelay) {
this.wood = BlockTypeId.fromString(wood);
this.leaves = BlockTypeId.fromString(leaves);
this.thinLeaves = BlockTypeId.fromString(thinLeaves);
Expand All @@ -61,6 +63,7 @@ public class ForestConfig {
this.maxSeedsPerGeneration = maxSeedsPerGeneration;
this.seedEveryGeneration = seedEveryGeneration;
this.randomGrowth = randomGrowth;
this.leafDecayDelay = leafDecayDelay;
}

public BlockTypeId getWood() {
Expand Down Expand Up @@ -120,5 +123,7 @@ public int getSeedEveryGeneration() {
public int getRandomGrowth() {
return randomGrowth;
}

public int getLeafDecayDelay() {
return leafDecayDelay;
}
}
19 changes: 16 additions & 3 deletions src/main/java/org/konstructs/forest/ForestPlugin.java
Expand Up @@ -16,8 +16,11 @@ public class ForestPlugin extends KonstructsActor {
private final BlockTypeId growsOn;
private final BlockTypeId seedsOn;
private final BlockTypeId sapling;
private final BlockTypeId wood;
private final int randomGrowth;
private final Random random = new Random();
private final ActorRef leafDecay;
private final Position leafDecayRadi;
private float speed = GlobalConfig.DEFAULT_SIMULATION_SPEED;

public ForestPlugin(String name, ActorRef universe, ForestConfig config) {
Expand All @@ -26,7 +29,11 @@ public ForestPlugin(String name, ActorRef universe, ForestConfig config) {
this.growsOn = config.getGrowsOn();
this.seedsOn = config.getSeedsOn();
this.sapling = config.getSapling();
this.wood = config.getWood();
this.randomGrowth = config.getRandomGrowth();
this.leafDecay = getContext().actorOf(LeafDecay.props(getUniverse(), config));
int radi = config.getCrownRadi() * 2;
this.leafDecayRadi = new Position(radi, radi, radi);
}

void tryToSeed(Position pos) {
Expand Down Expand Up @@ -71,7 +78,10 @@ public void onBoxQueryResult(BoxQueryResult result) {
public void onBlockUpdateEvent(BlockUpdateEvent update) {
for(Map.Entry<Position, BlockUpdate> p: update.getUpdatedBlocks().entrySet()) {
BlockTypeId after = p.getValue().getAfter().getType();
if(after.equals(sapling)) {
BlockTypeId before = p.getValue().getBefore().getType();
if(before.equals(wood) && !after.equals(wood)) {
getUniverse().tell(new BoxQuery(Box.createAround(p.getKey(), leafDecayRadi)), leafDecay);
} else if(after.equals(sapling)) {
seeded(p.getKey());
} else if(after.equals(growsOn) &&
random.nextInt(10000) <= randomGrowth) {
Expand All @@ -86,6 +96,7 @@ public void onBlockUpdateEvent(BlockUpdateEvent update) {
@Override
public void onGlobalConfig(GlobalConfig config) {
speed = config.getSimulationSpeed();
leafDecay.forward(config, getContext());
}

@Override
Expand Down Expand Up @@ -127,7 +138,8 @@ public void onReceive(Object message) {
@Config(key = "random-growth-delay") int randomGrowthDelay,
@Config(key = "max-seeds-per-generation") int maxSeedsPerGeneration,
@Config(key = "seed-every-generation") int seedEveryGeneration,
@Config(key = "random-growth") int randomGrowth
@Config(key = "random-growth") int randomGrowth,
@Config(key = "leaf-decay-delay") int leafDecayDelay
) {
Class currentClass = new Object() { }.getClass().getEnclosingClass();
ForestConfig config =
Expand All @@ -150,7 +162,8 @@ public void onReceive(Object message) {
randomGrowthDelay,
maxSeedsPerGeneration,
seedEveryGeneration,
randomGrowth);
randomGrowth,
leafDecayDelay);
return Props.create(currentClass, pluginName, universe, config);
}
}
91 changes: 91 additions & 0 deletions src/main/java/org/konstructs/forest/LeafDecay.java
@@ -0,0 +1,91 @@
package org.konstructs.forest;

import java.util.Set;
import java.util.Map;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Random;
import java.util.concurrent.TimeUnit;

import scala.concurrent.duration.Duration;
import scala.concurrent.duration.FiniteDuration;

import akka.actor.ActorRef;
import akka.actor.Props;
import akka.actor.Cancellable;

import konstructs.plugin.KonstructsActor;
import konstructs.api.*;
import konstructs.api.messages.*;

public class LeafDecay extends KonstructsActor {
private static class Trigger {}
private final Random random = new Random();
private final Position radi;
private final ActorRef leafRemover;
private final BlockTypeId leavesId;
private final BlockTypeId thinLeavesId;
private final ForestConfig config;
private Set<Position> leaves;
private float speed = GlobalConfig.DEFAULT_SIMULATION_SPEED;
private Cancellable scheduled;

LeafDecay(ActorRef universe, ForestConfig config) {
super(universe);
this.radi = new Position(config.getCrownRadi(), config.getCrownRadi(), config.getCrownRadi());
this.leaves = new HashSet<>();
this.leafRemover = getContext().actorOf(LeafRemover.props(getUniverse(), config));
this.leavesId = config.getLeaves();
this.thinLeavesId = config.getThinLeaves();
this.config = config;
this.scheduled = schedule();
}

private Cancellable schedule() {
FiniteDuration duration =
Duration.create((long)((float)config.getLeafDecayDelay() / speed),
TimeUnit.MILLISECONDS);
return getContext().system().scheduler().schedule(duration, duration, getSelf(), new Trigger(),
getContext().system().dispatcher(), getSelf());
}

@Override
public void onBoxQueryResult(BoxQueryResult result) {
Map<Position, BlockTypeId> placed = result.getAsMap();
for(Map.Entry<Position, BlockTypeId> p: placed.entrySet()) {
BlockTypeId type = p.getValue();
if(type.equals(leavesId) || type.equals(thinLeavesId))
leaves.add(p.getKey());
}
}

@Override
public void onGlobalConfig(GlobalConfig config) {
speed = config.getSimulationSpeed();
scheduled.cancel();
scheduled = schedule();
}

@Override
public void onReceive(Object message) {
if(message instanceof Trigger && leaves.size() > 0) {
int current = 0;
int find = random.nextInt(leaves.size());
for(Iterator<Position> i = leaves.iterator(); i.hasNext();) {
Position p = i.next();
if(current == find) { /* Random leaf found, try to remove it */
getUniverse().tell(new BoxQuery(Box.createAround(p, radi)), leafRemover);
i.remove();
return;
}
current++;
}
} else {
super.onReceive(message); // Handle konstructs messages
}
}

public static Props props(ActorRef universe, ForestConfig config) {
return Props.create(LeafDecay.class, universe, config);
}
}
47 changes: 47 additions & 0 deletions src/main/java/org/konstructs/forest/LeafRemover.java
@@ -0,0 +1,47 @@
package org.konstructs.forest;

import java.util.Arrays;

import akka.actor.ActorRef;
import akka.actor.Props;
import konstructs.plugin.KonstructsActor;
import konstructs.api.*;
import konstructs.api.messages.*;

public class LeafRemover extends KonstructsActor {
private final BlockFilter leavesFilter;
private final BlockTypeId wood;

LeafRemover(ActorRef universe, ForestConfig config) {
super(universe);
this.wood = config.getWood();
this.leavesFilter = BlockFilterFactory
.withBlockTypeId(config.getLeaves())
.or(BlockFilterFactory.withBlockTypeId(config.getThinLeaves()));
}

private Position getCenter(Box box) {
Position size = box.getSize();
return box
.getFrom()
.addX(size.getX() / 2)
.addY(size.getY() / 2)
.addZ(size.getZ() / 2);
}

private boolean findWood(BoxQueryResult result) {
return Arrays.asList(result.getBlocks()).contains(wood);
}

@Override
public void onBoxQueryResult(BoxQueryResult result) {
if(!findWood(result)) {
replaceWithVacuum(leavesFilter, getCenter(result.getBox()));
}
}

public static Props props(ActorRef universe, ForestConfig config) {
return Props.create(LeafRemover.class, universe, config);
}

}
3 changes: 3 additions & 0 deletions src/main/resources/reference.conf
Expand Up @@ -20,6 +20,7 @@ konstructs {
max-seeds-per-generation = 1
seed-every-generation = 4
random-growth = 2
leaf-decay-delay = 5000
}
org/konstructs/forest/beech {
class = "org.konstructs.forest.ForestPlugin"
Expand All @@ -42,6 +43,7 @@ konstructs {
max-seeds-per-generation = 3
seed-every-generation = 2
random-growth = 1
leaf-decay-delay = 5000
}
org/konstructs/forest/birch {
class = "org.konstructs.forest.ForestPlugin"
Expand All @@ -64,6 +66,7 @@ konstructs {
max-seeds-per-generation = 1
seed-every-generation = 3
random-growth = 6
leaf-decay-delay = 5000
}
org/konstructs/block-manager {
blocks {
Expand Down

0 comments on commit 9e3d49d

Please sign in to comment.