mirror of
https://github.com/BentoBoxWorld/Challenges.git
synced 2024-12-29 04:18:05 +01:00
Fix issue when players could complete ISLAND type challenges near island border and complete, if outside border are required blocks.
This commit is contained in:
parent
337defb452
commit
3b8b7129ad
@ -5,18 +5,21 @@ package world.bentobox.challenges.tasks;
|
||||
|
||||
|
||||
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;
|
||||
@ -693,69 +696,112 @@ public class TryToComplete
|
||||
*/
|
||||
private ChallengeResult checkSurrounding()
|
||||
{
|
||||
ChallengeResult result;
|
||||
Location playerLocation = this.user.getLocation();
|
||||
|
||||
if (!this.addon.getIslands().userIsOnIsland(this.user.getWorld(), this.user))
|
||||
// Init location in player position.
|
||||
BoundingBox boundingBox = new BoundingBox(playerLocation.getBlockX(),
|
||||
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))
|
||||
{
|
||||
// Player is not on island
|
||||
this.user.sendMessage("challenges.errors.not-on-island");
|
||||
result = EMPTY_RESULT;
|
||||
// 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);
|
||||
|
||||
if (boundingBox.getMinX() < island.getMinX())
|
||||
{
|
||||
boundingBox.expand(BlockFace.EAST, Math.abs(island.getMinX() - boundingBox.getMinX()));
|
||||
}
|
||||
|
||||
if (boundingBox.getMinZ() < island.getMinZ())
|
||||
{
|
||||
boundingBox.expand(BlockFace.NORTH, Math.abs(island.getMinZ() - boundingBox.getMinZ()));
|
||||
}
|
||||
|
||||
int range = island.getRange();
|
||||
|
||||
int islandMaxX = island.getMinX() + range * 2;
|
||||
int islandMaxZ = island.getMinZ() + range * 2;
|
||||
|
||||
if (boundingBox.getMaxX() > islandMaxX)
|
||||
{
|
||||
boundingBox.expand(BlockFace.WEST, Math.abs(boundingBox.getMaxX() - islandMaxX));
|
||||
}
|
||||
|
||||
if (boundingBox.getMaxZ() > islandMaxZ)
|
||||
{
|
||||
boundingBox.expand(BlockFace.SOUTH, Math.abs(boundingBox.getMaxZ() - islandMaxZ));
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
ChallengeResult result = this.searchForEntities(this.challenge.getRequiredEntities(), boundingBox);
|
||||
|
||||
if (result.meetsRequirements && !this.challenge.getRequiredBlocks().isEmpty())
|
||||
{
|
||||
// Check for items or entities in the area
|
||||
|
||||
result = this.searchForEntities(this.challenge.getRequiredEntities(), this.challenge.getSearchRadius());
|
||||
|
||||
if (result.meetsRequirements && !this.challenge.getRequiredBlocks().isEmpty())
|
||||
{
|
||||
// Search for items only if entities found
|
||||
result = this.searchForBlocks(this.challenge.getRequiredBlocks(), this.challenge.getSearchRadius());
|
||||
}
|
||||
|
||||
if (result.meetsRequirements &&
|
||||
this.challenge.isRemoveEntities() &&
|
||||
!this.challenge.getRequiredEntities().isEmpty())
|
||||
{
|
||||
this.removeEntities();
|
||||
}
|
||||
|
||||
if (result.meetsRequirements &&
|
||||
this.challenge.isRemoveBlocks() &&
|
||||
!this.challenge.getRequiredBlocks().isEmpty())
|
||||
{
|
||||
this.removeBlocks();
|
||||
}
|
||||
|
||||
// Check if challenge is repeated.
|
||||
result.setRepeat(this.manager.isChallengeComplete(this.user, this.world, this.challenge));
|
||||
// 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())
|
||||
{
|
||||
for (int y = -searchRadius; y <= searchRadius; y++)
|
||||
return new ChallengeResult().setMeetsRequirements();
|
||||
}
|
||||
|
||||
for (int x = (int) boundingBox.getMinX(); x <= boundingBox.getMaxX(); x++)
|
||||
{
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -765,7 +811,7 @@ public class TryToComplete
|
||||
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),
|
||||
@ -776,19 +822,30 @@ public class TryToComplete
|
||||
|
||||
|
||||
/**
|
||||
* 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())
|
||||
@ -806,19 +863,19 @@ public class TryToComplete
|
||||
|
||||
/**
|
||||
* 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()))
|
||||
{
|
||||
@ -835,8 +892,9 @@ public class TryToComplete
|
||||
|
||||
/**
|
||||
* 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());
|
||||
@ -846,7 +904,7 @@ public class TryToComplete
|
||||
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);
|
||||
|
Loading…
Reference in New Issue
Block a user