Adds ability to specify horizontal hit-box for end-rods and similar

This commit is contained in:
Kristian Knarvik 2023-09-27 23:13:03 +02:00
parent ccf43060dc
commit fc6bd33e87
9 changed files with 116 additions and 28 deletions

View File

@ -205,7 +205,7 @@ This command allows editing the specified property for the specified parkour are
These are all the options that can be changed for an arena.
| Option | Details |
|-----------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|---------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| name | The name of the arena. Used mainly to select the arena in commands. Note that underscore (_) cannot be used if you want to utilize placeholders, as it's used to split placeholder arguments. |
| spawnLocation | The spawn location of any player joining the arena. Use `56.546,64.0,44.45` to specify coordinates, or `here`, `this` or any other string to select your current location. |
| exitLocation | The location players will be sent to when exiting the arena. If not set, the player will be sent to where they joined from. Valid values are the same as for spawnLocation. |
@ -214,6 +214,7 @@ These are all the options that can be changed for an arena.
| checkpointAdd | Adds a new checkpoint to the arena's checkpoints (see spawnLocation for valid values). |
| checkpointClear | Clears all current checkpoints. Give any value to execute. If not given a value, current checkpoints are shown. |
| killPlaneBlocks | A comma-separated list of materials which will force a loss on hit. +WOOL and other [material tags](#notes-about-material-tags) are supported as well. |
| horizontalKillPlaneHitBox | The number of blocks away kill plane blocks will trigger horizontally (0-1). This only affects things less than 1 block wide, such as horizontal lightning and end rods. |
## Configuration options

View File

@ -38,6 +38,11 @@ public enum EditablePropertyType {
/**
* The property is a comma-separated list of materials
*/
MATERIAL_LIST
MATERIAL_LIST,
/**
* The property is any double value
*/
DOUBLE,
}

View File

@ -73,6 +73,11 @@ public class ParkourArena implements Arena {
*/
private @Nullable Set<Material> killPlaneBlocks;
/**
* The number of horizontal blocks the hit-box of kill plane blocks should cover
*/
private double horizontalKillPlaneHitBox;
/**
* The checkpoints for this arena. Entering a checkpoint overrides the player's spawn location.
*/
@ -97,6 +102,7 @@ public class ParkourArena implements Arena {
* @param winBlockType <p>The material of the block players have to hit to win this parkour arena</p>
* @param winLocation <p>The location a player has to reach to win this arena</p>
* @param killPlaneBlockNames <p>The names of the type of blocks</p>
* @param horizontalKillPlaneHitBox <p>The number of horizontal blocks the hit-box of kill plane blocks should cover</p>
* @param checkpoints <p>The checkpoints set for this arena</p>
* @param rewards <p>The rewards given by this arena</p>
* @param parkourArenaData <p>The arena data keeping track of which players have done what in this arena</p>
@ -104,7 +110,8 @@ public class ParkourArena implements Arena {
*/
public ParkourArena(@NotNull UUID arenaId, @NotNull String arenaName, @NotNull Location spawnLocation,
@Nullable Location exitLocation, @NotNull Material winBlockType, @Nullable Location winLocation,
@Nullable Set<String> killPlaneBlockNames, @NotNull List<Location> checkpoints,
@Nullable Set<String> killPlaneBlockNames, double horizontalKillPlaneHitBox,
@NotNull List<Location> checkpoints,
@NotNull Map<RewardCondition, Set<Reward>> rewards,
@NotNull ParkourArenaData parkourArenaData, @NotNull ParkourArenaHandler arenaHandler) {
this.arenaId = arenaId;
@ -116,6 +123,7 @@ public class ParkourArena implements Arena {
this.killPlaneBlockNames = killPlaneBlockNames;
this.killPlaneBlocks = this.killPlaneBlockNames == null ? null : MaterialHelper.loadMaterialList(
new ArrayList<>(killPlaneBlockNames), "+", MiniGames.getInstance().getLogger());
this.horizontalKillPlaneHitBox = horizontalKillPlaneHitBox;
this.checkpoints = checkpoints;
this.parkourArenaData = parkourArenaData;
this.parkourArenaHandler = arenaHandler;
@ -150,6 +158,7 @@ public class ParkourArena implements Arena {
this.killPlaneBlocks = null;
this.checkpoints = new ArrayList<>();
this.parkourArenaHandler = arenaHandler;
this.horizontalKillPlaneHitBox = 0.1;
}
@Override
@ -241,6 +250,37 @@ public class ParkourArena implements Arena {
return this.killPlaneBlockNames;
}
/**
* Gets the number of horizontal blocks the hit-box of kill plane blocks should cover
*
* <p>This is kind of hard to explain, but basically, when the player is less than the specified amount of blocks
* away from a kill plane block horizontally, a fail will be triggered. Sane values for this would usually be
* between 0.01 amd 1.</p>
*
* @return <p>The number of horizontal blocks the hit-box of kill plane blocks should cover</p>
*/
public double getHorizontalKillPlaneHitBox() {
return this.horizontalKillPlaneHitBox;
}
/**
* Sets the number of horizontal blocks the hit-box of kill plane blocks should cover
*
* <p>This is kind of hard to explain, but basically, when the player is less than the specified amount of blocks
* away from a kill plane block horizontally, a fail will be triggered. Sane values for this would usually be
* between 0.01 amd 1.</p>
*
* @param horizontalKillPlaneHitBox <p>The number of horizontal blocks the hit-box of kill plane blocks should cover</p>
*/
public boolean setHorizontalKillPlaneHitBox(double horizontalKillPlaneHitBox) {
if (horizontalKillPlaneHitBox > 1 || horizontalKillPlaneHitBox < -1) {
return false;
}
this.horizontalKillPlaneHitBox = horizontalKillPlaneHitBox;
this.saveArena();
return true;
}
/**
* Gets all checkpoint locations for this arena
*

View File

@ -62,7 +62,12 @@ public enum ParkourArenaEditableProperty {
*/
KILL_PLANE_BLOCKS("killPlaneBlocks", (arena) -> String.valueOf(arena.getKillPlaneBlockNames()),
EditablePropertyType.MATERIAL_LIST),
;
/**
* The horizontal hit-box of kill blocks
*/
HORIZONTAL_KILL_PLANE_HIT_BOX("horizontalKillPlaneHitBox",
(arena) -> String.valueOf(arena.getHorizontalKillPlaneHitBox()), EditablePropertyType.DOUBLE);
private final @NotNull String argumentString;
private final Function<ParkourArena, String> currentValueProvider;

View File

@ -42,6 +42,11 @@ public enum ParkourArenaStorageKey {
*/
KILL_PLANE_BLOCKS("killPlaneBlocks"),
/**
* The key for this arena's horizontal kill plane hit box
*/
HORIZONTAL_KILL_PLANE_HIT_BOX("horizontalKillPlaneHitBox"),
/**
* The key for this arena's checkpoint locations
*/

View File

@ -60,7 +60,12 @@ public class EditParkourArenaCommand implements CommandExecutor {
new String[]{editableProperty.getArgumentString(), value}));
return true;
} else {
boolean successful = changeValue(specifiedArena, editableProperty, arguments[2], player);
boolean successful;
try {
successful = changeValue(specifiedArena, editableProperty, arguments[2], player);
} catch (NumberFormatException exception) {
successful = false;
}
if (successful) {
stringFormatter.displaySuccessMessage(player, stringFormatter.replacePlaceholder(
MiniGameMessage.SUCCESS_PROPERTY_CHANGED, "{property}",
@ -80,9 +85,10 @@ public class EditParkourArenaCommand implements CommandExecutor {
* @param value <p>The new value of the property</p>
* @param player <p>The player trying to change the value</p>
* @return <p>True if the value was successfully changed</p>
* @throws NumberFormatException <p>If unable to parse a given numeric value</p>
*/
private boolean changeValue(@NotNull ParkourArena arena, @NotNull ParkourArenaEditableProperty property,
@NotNull String value, @NotNull Player player) {
@NotNull String value, @NotNull Player player) throws NumberFormatException {
return switch (property) {
case WIN_BLOCK_TYPE -> arena.setWinBlockType(parseMaterial(value));
case SPAWN_LOCATION -> arena.setSpawnLocation(parseLocation(player, value));
@ -92,6 +98,7 @@ public class EditParkourArenaCommand implements CommandExecutor {
case CHECKPOINT_ADD -> arena.addCheckpoint(parseLocation(player, value));
case CHECKPOINT_CLEAR -> arena.clearCheckpoints();
case KILL_PLANE_BLOCKS -> arena.setKillPlaneBlocks(new HashSet<>(List.of(value.split(","))));
case HORIZONTAL_KILL_PLANE_HIT_BOX -> arena.setHorizontalKillPlaneHitBox(Double.parseDouble(value));
};
}

View File

@ -261,7 +261,9 @@ public class MoveListener implements Listener {
}
// Create a hit-box approximate to the player's real hit-box
BoundingBox playerBox = new BoundingBox(0, -0.1, 0, 0.6, 1, 0.6).shift(
double horizontalHitBox = ((ParkourArena) arenaSession.getArena()).getHorizontalKillPlaneHitBox();
BoundingBox playerBox = new BoundingBox(-horizontalHitBox, -0.1, -horizontalHitBox,
0.6 + horizontalHitBox, 1, 0.6 + horizontalHitBox).shift(
toLocation).shift(-0.3, 0, -0.3);
for (Block block : adjustedBlocks) {
// For liquids, or anything without a proper collision shape, trigger collision

View File

@ -135,6 +135,7 @@ public final class ParkourArenaStorageHelper {
configSection.set(ParkourArenaStorageKey.WIN_BLOCK_TYPE.getKey(), new SerializableMaterial(arena.getWinBlockType()));
configSection.set(ParkourArenaStorageKey.WIN_LOCATION.getKey(), arena.getWinLocation());
configSection.set(ParkourArenaStorageKey.KILL_PLANE_BLOCKS.getKey(), getKillPlaneBlocks(arena));
configSection.set(ParkourArenaStorageKey.HORIZONTAL_KILL_PLANE_HIT_BOX.getKey(), arena.getHorizontalKillPlaneHitBox());
configSection.set(ParkourArenaStorageKey.CHECKPOINTS.getKey(), arena.getCheckpoints());
RewardStorageHelper.saveRewards(arena, configSection, ParkourArenaStorageKey.REWARDS.getKey());
saveParkourArenaData(arena.getData());
@ -208,6 +209,8 @@ public final class ParkourArenaStorageHelper {
} else {
killPlaneBlockNames = new HashSet<>((List<String>) killPlaneBlockNamesList);
}
double horizontalKillPlaneHitBox = configurationSection.getDouble(
ParkourArenaStorageKey.HORIZONTAL_KILL_PLANE_HIT_BOX.getKey(), 0);
List<Location> checkpoints = (List<Location>) configurationSection.get(ParkourArenaStorageKey.CHECKPOINTS.getKey());
Map<RewardCondition, Set<Reward>> rewards = RewardStorageHelper.loadRewards(configurationSection,
@ -239,7 +242,8 @@ public final class ParkourArenaStorageHelper {
}
return new ParkourArena(arenaId, arenaName, spawnLocation, exitLocation, winBlockType.getRawValue(), winLocation,
killPlaneBlockNames, checkpoints, rewards, arenaData, MiniGames.getInstance().getParkourArenaHandler());
killPlaneBlockNames, horizontalKillPlaneHitBox, checkpoints, rewards, arenaData,
MiniGames.getInstance().getParkourArenaHandler());
}
/**

View File

@ -104,11 +104,30 @@ public final class TabCompleteHelper {
tabCompleteSuggestions.put(EditablePropertyType.BLOCK_TYPE, getBlockTypeSuggestions());
tabCompleteSuggestions.put(EditablePropertyType.CHECKPOINT_CLEAR, getCheckpointClearSuggestions());
tabCompleteSuggestions.put(EditablePropertyType.MATERIAL_LIST, getMaterialListSuggestions());
tabCompleteSuggestions.put(EditablePropertyType.DOUBLE, getDoubleSuggestions());
}
return tabCompleteSuggestions.get(propertyType);
}
/**
* Gets suggestions for double values
*
* @return <p>A list of suggestions</p>
*/
private static List<String> getDoubleSuggestions() {
List<String> suggestions = new ArrayList<>();
suggestions.add("0");
suggestions.add("0.01");
suggestions.add("0.1");
suggestions.add("0.2");
suggestions.add("0.3");
suggestions.add("0.4");
suggestions.add("0.5");
suggestions.add("1");
return suggestions;
}
/**
* Gets suggestions for a list of materials
*