mirror of
https://github.com/BentoBoxWorld/Challenges.git
synced 2024-11-24 19:45:14 +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.GameMode;
|
||||||
|
import org.bukkit.Location;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.block.BlockFace;
|
||||||
import org.bukkit.entity.EntityType;
|
import org.bukkit.entity.EntityType;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.bukkit.util.Vector;
|
import org.bukkit.util.BoundingBox;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import world.bentobox.bentobox.api.localization.TextVariables;
|
import world.bentobox.bentobox.api.localization.TextVariables;
|
||||||
import world.bentobox.bentobox.api.user.User;
|
import world.bentobox.bentobox.api.user.User;
|
||||||
|
import world.bentobox.bentobox.database.objects.Island;
|
||||||
import world.bentobox.bentobox.util.Util;
|
import world.bentobox.bentobox.util.Util;
|
||||||
import world.bentobox.challenges.ChallengesAddon;
|
import world.bentobox.challenges.ChallengesAddon;
|
||||||
import world.bentobox.challenges.ChallengesManager;
|
import world.bentobox.challenges.ChallengesManager;
|
||||||
@ -693,69 +696,112 @@ public class TryToComplete
|
|||||||
*/
|
*/
|
||||||
private ChallengeResult checkSurrounding()
|
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
|
// Players should not be able to complete challenge if they stay near island with required blocks.
|
||||||
this.user.sendMessage("challenges.errors.not-on-island");
|
|
||||||
result = EMPTY_RESULT;
|
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
|
// Search for items only if entities found
|
||||||
|
result = this.searchForBlocks(this.challenge.getRequiredBlocks(), boundingBox);
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
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 map RequiredBlock Map.
|
||||||
* @param searchRadius Search distance
|
* @param boundingBox Bounding box of island challenge
|
||||||
* @return ChallengeResult
|
* @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);
|
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
|
// Remove one
|
||||||
blocks.computeIfPresent(mat, (b, amount) -> amount - 1);
|
blocks.computeIfPresent(mat, (b, amount) -> amount - 1);
|
||||||
// Remove any that have an amount of 0
|
// Remove any that have an amount of 0
|
||||||
blocks.entrySet().removeIf(en -> en.getValue() <= 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();
|
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",
|
blocks.forEach((k, v) -> user.sendMessage("challenges.errors.you-still-need",
|
||||||
"[amount]", String.valueOf(v),
|
"[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 map RequiredEntities Map.
|
||||||
* @param searchRadius Search distance
|
* @param boundingBox Bounding box of island challenge
|
||||||
* @return ChallengeResult
|
* @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);
|
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 -> {
|
this.user.getPlayer().getNearbyEntities(searchRadius, searchRadius, searchRadius).forEach(entity -> {
|
||||||
// Look through all the nearby Entities, filtering by type
|
// Check if entity is inside challenge bounding box
|
||||||
entities.computeIfPresent(entity.getType(), (reqEntity, amount) -> amount - 1);
|
if (boundingBox.contains(entity.getBoundingBox()))
|
||||||
entities.entrySet().removeIf(e -> e.getValue() == 0);
|
{
|
||||||
|
// 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())
|
if (entities.isEmpty())
|
||||||
@ -806,19 +863,19 @@ public class TryToComplete
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* This method removes required block and set air instead of it.
|
* 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());
|
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()))
|
if (blocks.containsKey(block.getType()))
|
||||||
{
|
{
|
||||||
@ -835,8 +892,9 @@ public class TryToComplete
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* This method removes required entities.
|
* 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() ?
|
Map<EntityType, Integer> entities = this.challenge.getRequiredEntities().isEmpty() ?
|
||||||
new EnumMap<>(EntityType.class) : new EnumMap<>(this.challenge.getRequiredEntities());
|
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 -> {
|
this.user.getPlayer().getNearbyEntities(searchRadius, searchRadius, searchRadius).forEach(entity -> {
|
||||||
// Look through all the nearby Entities, filtering by type
|
// 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.computeIfPresent(entity.getType(), (reqEntity, amount) -> amount - 1);
|
||||||
entities.entrySet().removeIf(e -> e.getValue() == 0);
|
entities.entrySet().removeIf(e -> e.getValue() == 0);
|
||||||
|
Loading…
Reference in New Issue
Block a user