Skip to content

Commit

Permalink
Fix issue when players could complete ISLAND type challenges near isl…
Browse files Browse the repository at this point in the history
…and border and complete, if outside border are required blocks.
  • Loading branch information
BONNe committed Apr 23, 2019
1 parent 337defb commit 3b8b712
Showing 1 changed file with 104 additions and 46 deletions.
150 changes: 104 additions & 46 deletions src/main/java/world/bentobox/challenges/tasks/TryToComplete.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,21 @@


import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.util.Vector;
import org.bukkit.util.BoundingBox;
import java.util.*;
import java.util.stream.Collectors;

import world.bentobox.bentobox.api.localization.TextVariables;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.database.objects.Island;
import world.bentobox.bentobox.util.Util;
import world.bentobox.challenges.ChallengesAddon;
import world.bentobox.challenges.ChallengesManager;
Expand Down Expand Up @@ -693,69 +696,112 @@ private boolean canIgnoreMeta(Material material)
*/
private ChallengeResult checkSurrounding()
{
ChallengeResult result;
Location playerLocation = this.user.getLocation();

if (!this.addon.getIslands().userIsOnIsland(this.user.getWorld(), this.user))
{
// Player is not on island
this.user.sendMessage("challenges.errors.not-on-island");
result = EMPTY_RESULT;
}
else
// Init location in player position.
BoundingBox boundingBox = new BoundingBox(playerLocation.getBlockX(),

This comment has been minimized.

Copy link
@Poslovitch

Poslovitch Apr 23, 2019

Member

You can use Player#getBoundingBox() here (Player extends Entity). Would that help you?

This comment has been minimized.

Copy link
@BONNe

BONNe Apr 24, 2019

Author Member

Oh, i forgot to change here:-) tq for reminding

playerLocation.getBlockY(),
playerLocation.getBlockZ(),
playerLocation.getBlockX(),
playerLocation.getBlockY(),
playerLocation.getBlockZ());

// Expand position with search radius.
boundingBox.expand(this.challenge.getSearchRadius());

if (ChallengesAddon.CHALLENGES_WORLD_PROTECTION.isSetForWorld(this.world))
{
// Check for items or entities in the area
// Players should not be able to complete challenge if they stay near island with required blocks.

Island island = this.addon.getIslands().getIsland(this.world, this.user);

result = this.searchForEntities(this.challenge.getRequiredEntities(), this.challenge.getSearchRadius());
if (boundingBox.getMinX() < island.getMinX())
{
boundingBox.expand(BlockFace.EAST, Math.abs(island.getMinX() - boundingBox.getMinX()));
}

if (result.meetsRequirements && !this.challenge.getRequiredBlocks().isEmpty())
if (boundingBox.getMinZ() < island.getMinZ())
{
// Search for items only if entities found
result = this.searchForBlocks(this.challenge.getRequiredBlocks(), this.challenge.getSearchRadius());
boundingBox.expand(BlockFace.NORTH, Math.abs(island.getMinZ() - boundingBox.getMinZ()));
}

if (result.meetsRequirements &&
this.challenge.isRemoveEntities() &&
!this.challenge.getRequiredEntities().isEmpty())
int range = island.getRange();

int islandMaxX = island.getMinX() + range * 2;
int islandMaxZ = island.getMinZ() + range * 2;

if (boundingBox.getMaxX() > islandMaxX)
{
this.removeEntities();
boundingBox.expand(BlockFace.WEST, Math.abs(boundingBox.getMaxX() - islandMaxX));
}

if (result.meetsRequirements &&
this.challenge.isRemoveBlocks() &&
!this.challenge.getRequiredBlocks().isEmpty())
if (boundingBox.getMaxZ() > islandMaxZ)
{
this.removeBlocks();
boundingBox.expand(BlockFace.SOUTH, Math.abs(boundingBox.getMaxZ() - islandMaxZ));
}
}

// Check if challenge is repeated.
result.setRepeat(this.manager.isChallengeComplete(this.user, this.world, this.challenge));
ChallengeResult result = this.searchForEntities(this.challenge.getRequiredEntities(), boundingBox);

if (result.meetsRequirements && !this.challenge.getRequiredBlocks().isEmpty())
{
// Search for items only if entities found
result = this.searchForBlocks(this.challenge.getRequiredBlocks(), boundingBox);
}

if (result.meetsRequirements &&
this.challenge.isRemoveEntities() &&
!this.challenge.getRequiredEntities().isEmpty())
{
this.removeEntities(boundingBox);
}

if (result.meetsRequirements &&
this.challenge.isRemoveBlocks() &&
!this.challenge.getRequiredBlocks().isEmpty())
{
this.removeBlocks(boundingBox);
}

// Check if challenge is repeated.
result.setRepeat(this.manager.isChallengeComplete(this.user, this.world, this.challenge));

return result;
}


/**
* This method search required blocks in given radius from user position.
* This method search required blocks in given challenge boundingBox.
* @param map RequiredBlock Map.
* @param searchRadius Search distance
* @param boundingBox Bounding box of island challenge
* @return ChallengeResult
*/
private ChallengeResult searchForBlocks(Map<Material, Integer> map, int searchRadius)
private ChallengeResult searchForBlocks(Map<Material, Integer> map, BoundingBox boundingBox)
{
Map<Material, Integer> blocks = new EnumMap<>(map);

for (int x = -searchRadius; x <= searchRadius; x++)
if (blocks.isEmpty())
{
return new ChallengeResult().setMeetsRequirements();
}

for (int x = (int) boundingBox.getMinX(); x <= boundingBox.getMaxX(); x++)
{
for (int y = -searchRadius; y <= searchRadius; y++)
for (int y = (int) boundingBox.getMinY(); y <= boundingBox.getMaxY(); y++)
{
for (int z = -searchRadius; z <= searchRadius; z++)
for (int z = (int) boundingBox.getMinZ(); z <= boundingBox.getMaxZ(); z++)
{
Material mat = this.user.getWorld().getBlockAt(this.user.getLocation().add(new Vector(x, y, z))).getType();
Material mat = this.user.getWorld().getBlockAt(x, y, z).getType();
// Remove one
blocks.computeIfPresent(mat, (b, amount) -> amount - 1);
// Remove any that have an amount of 0
blocks.entrySet().removeIf(en -> en.getValue() <= 0);

if (blocks.isEmpty())
{
// Return as soon as it s empty as no point to search more.
return new ChallengeResult().setMeetsRequirements();
}
}
}
}
Expand All @@ -765,7 +811,7 @@ private ChallengeResult searchForBlocks(Map<Material, Integer> map, int searchRa
return new ChallengeResult().setMeetsRequirements();
}

this.user.sendMessage("challenges.errors.not-close-enough", "[number]", String.valueOf(searchRadius));
this.user.sendMessage("challenges.errors.not-close-enough", "[number]", String.valueOf(this.challenge.getSearchRadius()));

blocks.forEach((k, v) -> user.sendMessage("challenges.errors.you-still-need",
"[amount]", String.valueOf(v),
Expand All @@ -776,19 +822,30 @@ private ChallengeResult searchForBlocks(Map<Material, Integer> map, int searchRa


/**
* This method search required entities in given radius from user position.
* This method search required entities in given radius from user position and entity is inside boundingBox.
* @param map RequiredEntities Map.
* @param searchRadius Search distance
* @param boundingBox Bounding box of island challenge
* @return ChallengeResult
*/
private ChallengeResult searchForEntities(Map<EntityType, Integer> map, int searchRadius)
private ChallengeResult searchForEntities(Map<EntityType, Integer> map, BoundingBox boundingBox)
{
Map<EntityType, Integer> entities = map.isEmpty() ? new EnumMap<>(EntityType.class) : new EnumMap<>(map);

if (entities.isEmpty())
{
return new ChallengeResult().setMeetsRequirements();
}

int searchRadius = this.challenge.getSearchRadius();

this.user.getPlayer().getNearbyEntities(searchRadius, searchRadius, searchRadius).forEach(entity -> {
// Look through all the nearby Entities, filtering by type
entities.computeIfPresent(entity.getType(), (reqEntity, amount) -> amount - 1);
entities.entrySet().removeIf(e -> e.getValue() == 0);
// Check if entity is inside challenge bounding box
if (boundingBox.contains(entity.getBoundingBox()))
{
// Look through all the nearby Entities, filtering by type
entities.computeIfPresent(entity.getType(), (reqEntity, amount) -> amount - 1);
entities.entrySet().removeIf(e -> e.getValue() == 0);
}
});

if (entities.isEmpty())
Expand All @@ -806,19 +863,19 @@ private ChallengeResult searchForEntities(Map<EntityType, Integer> map, int sear

/**
* This method removes required block and set air instead of it.
* @param boundingBox Bounding box of island challenge
*/
private void removeBlocks()
private void removeBlocks(BoundingBox boundingBox)
{
Map<Material, Integer> blocks = new EnumMap<>(this.challenge.getRequiredBlocks());
int searchRadius = this.challenge.getSearchRadius();

for (int x = -searchRadius; x <= searchRadius; x++)
for (int x = (int) boundingBox.getMinX(); x <= boundingBox.getMaxX(); x++)
{
for (int y = -searchRadius; y <= searchRadius; y++)
for (int y = (int) boundingBox.getMinY(); y <= boundingBox.getMaxY(); y++)
{
for (int z = -searchRadius; z <= searchRadius; z++)
for (int z = (int) boundingBox.getMinZ(); z <= boundingBox.getMaxZ(); z++)
{
Block block = this.user.getWorld().getBlockAt(this.user.getLocation().add(new Vector(x, y, z)));
Block block = this.user.getWorld().getBlockAt(new Location(this.user.getWorld(), x, y, z));

if (blocks.containsKey(block.getType()))
{
Expand All @@ -835,8 +892,9 @@ private void removeBlocks()

/**
* This method removes required entities.
* @param boundingBox Bounding box of island challenge
*/
private void removeEntities()
private void removeEntities(BoundingBox boundingBox)
{
Map<EntityType, Integer> entities = this.challenge.getRequiredEntities().isEmpty() ?
new EnumMap<>(EntityType.class) : new EnumMap<>(this.challenge.getRequiredEntities());
Expand All @@ -846,7 +904,7 @@ private void removeEntities()
this.user.getPlayer().getNearbyEntities(searchRadius, searchRadius, searchRadius).forEach(entity -> {
// Look through all the nearby Entities, filtering by type

if (entities.containsKey(entity.getType()))
if (entities.containsKey(entity.getType()) && boundingBox.contains(entity.getBoundingBox()))
{
entities.computeIfPresent(entity.getType(), (reqEntity, amount) -> amount - 1);
entities.entrySet().removeIf(e -> e.getValue() == 0);
Expand Down

0 comments on commit 3b8b712

Please sign in to comment.