Reworked data saving and now use bounding box.

This commit is contained in:
tastybento 2019-05-08 15:21:11 -07:00
parent d6fd3e4da1
commit 930d29acfc
12 changed files with 74 additions and 290 deletions

View File

@ -1,20 +1,18 @@
package world.bentobox.greenhouses.data;
import java.awt.Rectangle;
import java.util.UUID;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.Biome;
import org.bukkit.util.BoundingBox;
import com.google.gson.annotations.Expose;
import world.bentobox.bentobox.database.objects.DataObject;
import world.bentobox.bentobox.database.objects.adapters.Adapter;
import world.bentobox.greenhouses.data.adapters.BiomeRecipeAdapter;
import world.bentobox.greenhouses.data.adapters.RectangleAdapter;
import world.bentobox.greenhouses.greenhouse.BiomeRecipe;
import world.bentobox.greenhouses.greenhouse.Walls;
import world.bentobox.greenhouses.managers.RecipeManager;
/**
* Greenhouse object
@ -23,33 +21,18 @@ import world.bentobox.greenhouses.greenhouse.Walls;
*/
public class Greenhouse implements DataObject {
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "Greenhouse [uniqueId=" + uniqueId + ", location=" + location + ", footprint=" + footprint
+ ", ceilingHeight=" + ceilingHeight + ", originalBiome=" + originalBiome
+ ", roofHopperLocation=" + roofHopperLocation + ", biomeRecipe=" + biomeRecipe.getName()
+ ", broken=" + broken + "]";
}
@Expose
private String uniqueId = UUID.randomUUID().toString();
@Expose
private Location location;
@Expose
@Adapter(RectangleAdapter.class)
private Rectangle footprint;
@Expose
private int ceilingHeight;
private BoundingBox boundingBox;
@Expose
private Biome originalBiome;
@Expose
private Location roofHopperLocation;
@Expose
@Adapter(BiomeRecipeAdapter.class)
private BiomeRecipe biomeRecipe;
private String biomeRecipeName;
private boolean broken;
@ -60,22 +43,22 @@ public class Greenhouse implements DataObject {
public Greenhouse(World world, Walls walls, int ceilingHeight) {
this.location = new Location(world, walls.getMinX(), walls.getFloor(), walls.getMinZ());
this.ceilingHeight = ceilingHeight;
this.footprint = new Rectangle(walls.getMinX(), walls.getMinZ(), walls.getWidth(), walls.getLength());
Location location2 = new Location(world, walls.getMaxX(), ceilingHeight, walls.getMaxZ());
this.boundingBox = BoundingBox.of(location, location2);
}
/**
* @return the biomeRecipe
*/
public BiomeRecipe getBiomeRecipe() {
return biomeRecipe;
public String getBiomeRecipeName() {
return biomeRecipeName;
}
/**
* @return the ceilingHeight
*/
public int getCeilingHeight() {
return ceilingHeight;
return (int) boundingBox.getMaxY();
}
/**
@ -85,13 +68,6 @@ public class Greenhouse implements DataObject {
return location.getBlockY();
}
/**
* @return the floor
*/
public Rectangle getFootprint() {
return footprint;
}
/**
* @return the location
*/
@ -129,10 +105,10 @@ public class Greenhouse implements DataObject {
}
/**
* @param biomeRecipe the biomeRecipe to set
* @param biomeRecipeName the biomeRecipe to set
*/
public void setBiomeRecipe(BiomeRecipe biomeRecipe) {
this.biomeRecipe = biomeRecipe;
public void setBiomeRecipeName(String biomeRecipeName) {
this.biomeRecipeName = biomeRecipeName;
}
/**
@ -142,20 +118,6 @@ public class Greenhouse implements DataObject {
this.broken = broken;
}
/**
* @param ceilingHeight the ceilingHeight to set
*/
public void setCeilingHeight(int ceilingHeight) {
this.ceilingHeight = ceilingHeight;
}
/**
* @param floor the floor to set
*/
public void setFootprint(Rectangle floor) {
this.footprint = floor;
}
/**
* @param location the location to set
*/
@ -177,6 +139,20 @@ public class Greenhouse implements DataObject {
this.roofHopperLocation = roofHopperLocation;
}
/**
* @return the boundingBox
*/
public BoundingBox getBoundingBox() {
return boundingBox;
}
/**
* @param boundingBox the boundingBox to set
*/
public void setBoundingBox(BoundingBox boundingBox) {
this.boundingBox = boundingBox;
}
/* (non-Javadoc)
* @see world.bentobox.bentobox.database.objects.DataObject#setUniqueId(java.lang.String)
*/
@ -191,7 +167,7 @@ public class Greenhouse implements DataObject {
* @return internal area of greenhouse
*/
public int getArea() {
return (this.footprint.height - 2) * (this.footprint.width - 2);
return ((int)boundingBox.getWidthX() - 2) * ((int)boundingBox.getWidthZ() - 2);
}
/**
@ -207,13 +183,24 @@ public class Greenhouse implements DataObject {
* @return true if inside the greenhouse
*/
public boolean contains(Location location2) {
return (location.getWorld().equals(location2.getWorld())
&& location2.getBlockY() <= this.ceilingHeight
&& location2.getBlockY() >= this.getFloorHeight()
&& location2.getBlockX() >= (int)this.footprint.getMinX()
&& location2.getBlockX() <= (int)this.footprint.getMaxX()
&& location2.getBlockZ() >= (int)this.footprint.getMinY()
&& location2.getBlockZ() <= (int)this.footprint.getMaxY());
return location.getWorld().equals(location2.getWorld()) && boundingBox.contains(location2.toVector());
}
/**
* Set the biome recipe
* @param greenhouseRecipe - biome recipe
*/
public void setBiomeRecipe(BiomeRecipe greenhouseRecipe) {
this.biomeRecipeName = greenhouseRecipe.getName();
}
/**
* Get the biome recipe for this greenhouse
* @return biome recipe or null
*/
public BiomeRecipe getBiomeRecipe() {
return RecipeManager.getBiomeRecipies(biomeRecipeName).orElse(null);
}
}

View File

@ -1,29 +0,0 @@
package world.bentobox.greenhouses.data.adapters;
import world.bentobox.bentobox.database.objects.adapters.AdapterInterface;
import world.bentobox.greenhouses.greenhouse.BiomeRecipe;
import world.bentobox.greenhouses.managers.RecipeManager;
/**
* @author tastybento
*
*/
public class BiomeRecipeAdapter implements AdapterInterface<BiomeRecipe, String> {
@Override
public BiomeRecipe deserialize(Object object) {
if (object instanceof String && ((String)object).equals("null")) {
return null;
}
return RecipeManager.getBiomeRecipies((String)object).orElse(null);
}
@Override
public String serialize(Object object) {
if (object == null) {
return "null";
}
return ((BiomeRecipe)object).getName();
}
}

View File

@ -1,32 +0,0 @@
package world.bentobox.greenhouses.data.adapters;
import java.awt.Rectangle;
import world.bentobox.bentobox.database.objects.adapters.AdapterInterface;
/**
* @author tastybento
*
*/
public class RectangleAdapter implements AdapterInterface<Rectangle, String> {
@Override
public Rectangle deserialize(Object object) {
if (object instanceof String) {
if (!((String)object).equals("null")) {
String[] s = ((String)object).split(",");
if (s.length == 4) {
return new Rectangle(Integer.valueOf(s[0]), Integer.valueOf(s[1]), Integer.valueOf(s[2]), Integer.valueOf(s[3]));
}
}
}
return null;
}
@Override
public String serialize(Object object) {
Rectangle r = (Rectangle)object;
return r == null ? "null" : r.x + ","+ r.y + "," + r.width + "," + r.height;
}
}

View File

@ -24,7 +24,7 @@ import world.bentobox.greenhouses.data.Greenhouse;
import world.bentobox.greenhouses.managers.GreenhouseManager.GreenhouseResult;
public class BiomeRecipe implements Comparable<BiomeRecipe> {
private final Greenhouses addon;
private Greenhouses addon;
private Biome type;
private Material icon; // Biome icon for control panel
private int priority;
@ -56,6 +56,8 @@ public class BiomeRecipe implements Comparable<BiomeRecipe> {
private final Random random = new Random();
private Map<Material, Integer> missingBlocks;
public BiomeRecipe() {}
/**
* @param type - biome
* @param priority - priority (higher is better)
@ -138,8 +140,8 @@ public class BiomeRecipe implements Comparable<BiomeRecipe> {
Map<Material, Integer> blockCount = new HashMap<>();
// Look through the greenhouse and count what is in there
for (int y = gh.getFloorHeight(); y< gh.getCeilingHeight();y++) {
for (int x = (int) (gh.getFootprint().getMinX()+1); x < gh.getFootprint().getMaxX(); x++) {
for (int z = (int) (gh.getFootprint().getMinY()+1); z < gh.getFootprint().getMaxY(); z++) {
for (int x = (int) (gh.getBoundingBox().getMinX()+1); x < gh.getBoundingBox().getMaxX(); x++) {
for (int z = (int) (gh.getBoundingBox().getMinZ()+1); z < gh.getBoundingBox().getMaxZ(); z++) {
Block b = gh.getWorld().getBlockAt(x, y, z);
if (!b.getType().equals(Material.AIR)) {
blockCount.putIfAbsent(b.getType(), 0);
@ -442,4 +444,5 @@ public class BiomeRecipe implements Comparable<BiomeRecipe> {
public Set<EntityType> getMobTypes() {
return mobTree == null ? Collections.emptySet() : mobTree.values().stream().map(GreenhouseMob::getMobType).collect(Collectors.toSet());
}
}

View File

@ -125,10 +125,10 @@ public class GreenhouseEvents implements Listener {
plugin.getManager().getMap().getGreenhouse(e.getBlock().getLocation()).ifPresent(g -> {
// Check to see if wall or roof block broken
if ((e.getBlock().getLocation().getBlockY() == g.getCeilingHeight())
|| e.getBlock().getLocation().getBlockX() == g.getFootprint().getMinX()
|| e.getBlock().getLocation().getBlockX() == g.getFootprint().getMaxX()
|| e.getBlock().getLocation().getBlockZ() == g.getFootprint().getMinY()
|| e.getBlock().getLocation().getBlockZ() == g.getFootprint().getMaxY()
|| e.getBlock().getLocation().getBlockX() == (int)g.getBoundingBox().getMinX()
|| e.getBlock().getLocation().getBlockX() == (int)g.getBoundingBox().getMaxX()
|| e.getBlock().getLocation().getBlockZ() == (int)g.getBoundingBox().getMinY()
|| e.getBlock().getLocation().getBlockZ() == (int)g.getBoundingBox().getMaxY()
) {
user.sendMessage("greenhouses.broken");
plugin.getManager().getMap().removeGreenhouse(g);

View File

@ -41,8 +41,8 @@ public class SnowTracker implements Listener {
private void getAirBlocks(Greenhouse gh) {
List<Block> waterBlocks = new ArrayList<>();
for (int x = (int)gh.getFootprint().getMinX() + 1; x < (int)gh.getFootprint().getMaxX(); x++) {
for (int z = (int)gh.getFootprint().getMinY() + 1; z < (int)gh.getFootprint().getMaxY(); z++) {
for (int x = (int)gh.getBoundingBox().getMinX() + 1; x < (int)gh.getBoundingBox().getMaxX(); x++) {
for (int z = (int)gh.getBoundingBox().getMinY() + 1; z < (int)gh.getBoundingBox().getMaxY(); z++) {
for (int y = gh.getCeilingHeight() - 1; y >= gh.getFloorHeight(); y--) {
Block b = gh.getLocation().getWorld().getBlockAt(x, y, z);
if (b.getType().equals(Material.AIR) || b.getType().equals(Material.SNOW)) {

View File

@ -142,8 +142,8 @@ class EcoSystemManager {
*/
private List<Block> getAvailableBlocks(Greenhouse gh) {
List<Block> result = new ArrayList<>();
for (int x = (int)gh.getFootprint().getMinX() + 1; x < (int)gh.getFootprint().getMaxX(); x++) {
for (int z = (int)gh.getFootprint().getMinY() + 1; z < (int)gh.getFootprint().getMaxY(); z++) {
for (int x = (int)gh.getBoundingBox().getMinX() + 1; x < (int)gh.getBoundingBox().getMaxX(); x++) {
for (int z = (int)gh.getBoundingBox().getMinY() + 1; z < (int)gh.getBoundingBox().getMaxY(); z++) {
for (int y = gh.getCeilingHeight() - 1; y >= gh.getFloorHeight(); y--) {
Block b = gh.getLocation().getWorld().getBlockAt(x, y, z);
if (!b.getType().equals(Material.AIR) && b.getRelative(BlockFace.UP).getType().equals(Material.AIR)) {

View File

@ -116,8 +116,8 @@ public class GreenhouseManager implements Listener {
addon.log("Returning biome to original state: " + g.getOriginalBiome().toString());
if (g.getOriginalBiome().equals(Biome.NETHER) || g.getOriginalBiome().equals(Biome.DESERT)
|| g.getOriginalBiome().equals(Biome.DESERT_HILLS)) {
for (int x = (int)g.getFootprint().getMinX(); x<= (int)g.getFootprint().getMaxX(); x++) {
for (int z = (int)g.getFootprint().getMinY(); z<= (int)g.getFootprint().getMinY(); z++) {
for (int x = (int)g.getBoundingBox().getMinX(); x<= (int)g.getBoundingBox().getMaxX(); x++) {
for (int z = (int)g.getBoundingBox().getMinY(); z<= (int)g.getBoundingBox().getMinY(); z++) {
// Set back to the original biome
g.getLocation().getWorld().setBiome(x, z, g.getOriginalBiome());
for (int y = g.getFloorHeight(); y< g.getCeilingHeight(); y++) {
@ -158,7 +158,7 @@ public class GreenhouseManager implements Listener {
if (resultSet.isEmpty()) {
// Success - set recipe and add to map
finder.getGh().setBiomeRecipe(greenhouseRecipe);
map.addGreenhouse(finder.getGh());
resultSet.add(map.addGreenhouse(finder.getGh()));
activateGreenhouse(finder.getGh());
}
return new GhResult().setFinder(finder).setResults(resultSet);
@ -177,8 +177,8 @@ public class GreenhouseManager implements Listener {
}
private void activateGreenhouse(Greenhouse gh) {
for (int x = gh.getFootprint().x; x < gh.getFootprint().x + gh.getFootprint().width; x++) {
for (int z = gh.getFootprint().y; z < gh.getFootprint().y + gh.getFootprint().height; z++) {
for (int x = (int)gh.getBoundingBox().getMinX(); x < gh.getBoundingBox().getMaxX(); x++) {
for (int z = (int)gh.getBoundingBox().getMinZ(); z < gh.getBoundingBox().getMaxZ(); z++) {
gh.getWorld().setBiome(x, z, gh.getBiomeRecipe().getBiome());
}
}
@ -223,6 +223,14 @@ public class GreenhouseManager implements Listener {
return this;
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "GhResult [results=" + results + ", finder=" + finder + "]";
}
}
}

View File

@ -82,7 +82,7 @@ public class GreenhouseMap {
private boolean isOverlapping(Greenhouse greenhouse) {
return addon.getIslands().getIslandAt(greenhouse.getLocation()).map(i -> {
greenhouses.putIfAbsent(i, new ArrayList<>());
return greenhouses.get(i).stream().anyMatch(g -> g.getFootprint().intersects(greenhouse.getFootprint()));
return greenhouses.get(i).stream().anyMatch(g -> g.getBoundingBox().overlaps(greenhouse.getBoundingBox()));
}).orElse(false);
}

View File

@ -66,7 +66,7 @@ class MakeCommand extends CompositeCommand {
return false;
}
GhResult result = ((Greenhouses)this.getAddon()).getManager().tryToMakeGreenhouse(location, br);
getAddon().getPlugin().logDebug(result);
if (result.getResults().contains(GreenhouseResult.SUCCESS)) {
// Success
user.sendMessage("greenhouses.commands.user.make.success", "[biome]", result.getFinder().getGh().getBiomeRecipe().getFriendlyName());

View File

@ -1,91 +0,0 @@
/**
*
*/
package world.bentobox.greenhouses.data.adapters;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.util.Optional;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import world.bentobox.greenhouses.greenhouse.BiomeRecipe;
import world.bentobox.greenhouses.managers.RecipeManager;
/**
* @author tastybento
*
*/
@RunWith(PowerMockRunner.class)
@PrepareForTest( {RecipeManager.class} )
public class BiomeRecipeAdapterTest {
private BiomeRecipeAdapter bra;
private BiomeRecipe recipe;
/**
* @throws java.lang.Exception
*/
@Before
public void setUp() throws Exception {
bra = new BiomeRecipeAdapter();
PowerMockito.mockStatic(RecipeManager.class);
recipe = mock(BiomeRecipe.class);
Optional<BiomeRecipe> optionalRecipe = Optional.of(recipe);
when(RecipeManager.getBiomeRecipies(Mockito.eq("recipe_name"))).thenReturn(optionalRecipe);
when(RecipeManager.getBiomeRecipies(Mockito.eq("nothing"))).thenReturn(Optional.empty());
}
/**
* Test method for {@link world.bentobox.greenhouses.data.adapters.BiomeRecipeAdapter#deserialize(java.lang.Object)}.
*/
@Test
public void testDeserialize() {
assertEquals(recipe, bra.deserialize("recipe_name"));
}
/**
* Test method for {@link world.bentobox.greenhouses.data.adapters.BiomeRecipeAdapter#deserialize(java.lang.Object)}.
*/
@Test
public void testDeserializeNoRecipe() {
assertNull(bra.deserialize("nothing"));
}
/**
* Test method for {@link world.bentobox.greenhouses.data.adapters.BiomeRecipeAdapter#deserialize(java.lang.Object)}.
*/
@Test
public void testDeserializeNull() {
assertNull(bra.deserialize("null"));
}
/**
* Test method for {@link world.bentobox.greenhouses.data.adapters.BiomeRecipeAdapter#serialize(java.lang.Object)}.
*/
@Test
public void testSerialize() {
BiomeRecipe br = mock(BiomeRecipe.class);
when(br.getName()).thenReturn("recipe_name");
assertEquals("recipe_name", bra.serialize(br));
}
/**
* Test method for {@link world.bentobox.greenhouses.data.adapters.BiomeRecipeAdapter#serialize(java.lang.Object)}.
*/
@Test
public void testSerializeNull() {
assertEquals("null", bra.serialize(null));
}
}

View File

@ -1,62 +0,0 @@
/**
*
*/
package world.bentobox.greenhouses.data.adapters;
import static org.junit.Assert.*;
import java.awt.Rectangle;
import org.junit.Before;
import org.junit.Test;
/**
* @author tastybento
*
*/
public class RectangleAdapterTest {
private RectangleAdapter ra;
/**
* @throws java.lang.Exception
*/
@Before
public void setUp() throws Exception {
ra = new RectangleAdapter();
}
/**
* Test method for {@link world.bentobox.greenhouses.data.adapters.RectangleAdapter#Serialize(java.lang.Object)}.
*/
@Test
public void testSerialize() {
Rectangle rectangle = new Rectangle(10,20,30,40);;
assertEquals("10,20,30,40", ra.serialize(rectangle));
}
/**
* Test method for {@link world.bentobox.greenhouses.data.adapters.RectangleAdapter#serialize(java.lang.Object)}.
*/
@Test
public void testSerializeNull() {
assertEquals("null", ra.serialize(null));
}
/**
* Test method for {@link world.bentobox.greenhouses.data.adapters.RectangleAdapter#serialize(java.lang.Object)}.
*/
@Test
public void testDeserialize() {
Rectangle rectangle = new Rectangle(10,20,30,40);;
assertEquals(rectangle, ra.deserialize("10,20,30,40"));
}
/**
* Test method for {@link world.bentobox.greenhouses.data.adapters.RectangleAdapter#deserialize(java.lang.Object)}.
*/
@Test
public void testDeserializeNull() {
assertNull(ra.deserialize("null"));
}
}