Skip to content

Commit

Permalink
Ceilings and Broadcast Precision (#168)
Browse files Browse the repository at this point in the history
Squashed with the following changes:
* Update Actions Toolchain, Add JDK 19
* Rework height-checks against flag base.
* Add option to use precise location of a flag in broadcasts.
* Update CHANGELOG.md

Issues to be ironed out as they become apparent.
  • Loading branch information
TheFlagCourier authored Oct 20, 2022
1 parent 5cdbad8 commit ef578a6
Show file tree
Hide file tree
Showing 12 changed files with 160 additions and 39 deletions.
8 changes: 4 additions & 4 deletions .github/workflows/compile-on-push.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@ name: Maven Compile (Multiple JDK)
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
strategy:
matrix:
java: ['16', '17']
java: ['16', '17', '19']
name: Java ${{ matrix.java }}
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Set up Java
uses: actions/setup-java@v2
uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: ${{ matrix.java }}
Expand Down
33 changes: 19 additions & 14 deletions .idea/checkstyle-idea.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 10 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,30 @@

The format is based on [Keep a Changelog][Keep a Changelog], and this project adheres to [Semantic Versioning][semver].

If a change is missing, it is likely simple or was forgotten about when this log was updated. 😓

Feel free to PR corrections to this file.

## [Unreleased][Unreleased]

### Known-Issues
- Impossible to attack plots that have
- [Possibly fixed: See #168](https://github.com/TownyAdvanced/FlagWar/pull/168) — Impossible to attack plots that have
[blocks placed at world build height](https://github.com/TownyAdvanced/FlagWar/issues/84). Marked as release-blocker.
- Use JitPack is not reliable for builds > 0.5.2 due to issues fetching from `apache.snapshots`. This is being looked into.

### Added

- Russian Translation ([#101](https://github.com/TownyAdvanced/FlagWar/pull/101), [@HighError][HighError])
- Accuracy switch for broadcast locations. ([#168](https://github.com/TownyAdvanced/FlagWar/pull/168))
- Ability to place flags in worlds marked as having ceilings. ([#168](https://github.com/TownyAdvanced/FlagWar/pull/168))
- Sea-level based restrictions added to compensate.
- Feature: Neighbouring plots protect from attack. ([#141](https://github.com/TownyAdvanced/FlagWar/pull/141), [@LlmDl][LlmDl])

### Changed

- Update usages of the deprecated `TownyMessaging#sendResidentMessage` calls to use Spigot's `Player#sendMessage`.
([#108](https://github.com/TownyAdvanced/FlagWar/pull/108), [@LlmDl][LlmDl])
- Updated Dependencies (via [Dependabot][Dependabot])
- Switch Towny repository from JitPack to Glare's Repository.
- Allow for an empty editable materials list. ([#117](https://github.com/TownyAdvanced/FlagWar/pull/117), [@LlmDl][LlmDl])
- Switch Towny repository from JitPack to Glare's Repository.
- Update the static min towny versions. ([#142](https://github.com/TownyAdvanced/FlagWar/pull/142), [@LlmDl][LlmDl])
Expand Down
43 changes: 43 additions & 0 deletions docs/issue84.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Working Doc: Issue 84

<!-- TODO: Delete this file before merge -->
## Impossible to attack a plot that has blocks placed at world build-height limit.

- [GitHub](https://github.com/TownyAdvanced/FlagWar/issues/84)

### Summary

If an attacking player is attempting to flag a plot, and a ceiling exists
above the flag location, the flag will not be placeable. Some defending
players will take advantage of this fact by placing a plot-wide ceiling
at a world's maximum build height.

This issue also extends to worlds with natural ceilings such as worlds
using the default Nether generator settings.

This issue stems from design decisions as old as the general-audience
release of the game. As such, this issue is a natural bug. It is also
classified as a blocker for future official FlagWar releases due to its
exploit-ability.

### Proposed Solution

This issue should be easily addressed by applying a few hard-coded rules
to when and where a war-flag may be placed.

- [x] Allow placing flags under ceilings. (Required)
- [x] Traditional check: In a world without a natural ceiling, and the highest block is within 5 meters of max height.
- [x] Add a basic height check:
- [x] (submersion) checks for if a flag base has a liquid up to 4 meters above it
- [x] (general space) check same vertical space for any non-empty, non-liquid blocks
- [x] Add sea-level (minus depth) check
- Flag base must be at or above a world's sea-level, minus modifier.
- Default modifier: 12 meters

- [x] Rework Coordinate Broadcasting

- [ ] ~~Specific Audience Options (_Config_)~~
- This specific plan was scrapped.
- [x] Location Accuracy (_Config_)
- towny (_Towny Coord, default_)
- precise (_Minecraft's X,Y,Z_)
8 changes: 4 additions & 4 deletions jitpack.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
before_install:
- source "$HOME/.sdkman/bin/sdkman-init.sh"
- sdk update
- sdk install java 17.0.0-ms
- sdk use java 17.0.0-ms
- sdk install maven 3.8.3
- sdk use maven 3.8.3
- sdk install java 17.0.3-ms
- sdk use java 17.0.3-ms
- sdk install maven 3.8.6
- sdk use maven 3.8.6
55 changes: 40 additions & 15 deletions src/main/java/io/github/townyadvanced/flagwar/FlagWar.java
Original file line number Diff line number Diff line change
Expand Up @@ -479,7 +479,7 @@ public static void checkBlock(final Player player, final Block block, final Canc
public static boolean callAttackCellEvent(final Towny towny, final Player player, final Block block,
final WorldCoord worldCoord) throws TownyException {

checkFlagHeight(block);
flagPlacementChecks(block);

var townyUniverse = TownyUniverse.getInstance();
var attackingResident = townyUniverse.getResident(player.getUniqueId());
Expand All @@ -494,13 +494,8 @@ public static boolean callAttackCellEvent(final Towny towny, final Player player
throw new TownyException(Translate.fromPrefixed("error.player-not-in-nation"));
}

if (attackingResident.hasTown()) {
if (attackingResident.hasTown() && attackingResident.hasNation()) {
attackingTown = attackingResident.getTown();
} else {
return false;
}

if (attackingResident.hasNation()) {
attackingNation = attackingResident.getNation();
} else {
return false;
Expand Down Expand Up @@ -550,11 +545,48 @@ && isThisPlotProtectedByNeighbours(worldCoord)) {
setAttackerAsEnemy(landOwnerNation, attackingNation);
towny.updateCache(worldCoord);

String coordinates = worldCoord.toString();
if (FlagWarConfig.getBroadcastAccuracy().equalsIgnoreCase("precise")) {
coordinates = String.format("%d, %d, %d", block.getX(), block.getY(), block.getZ());
}

TownyMessaging.sendGlobalMessage(Translate.fromPrefixed("broadcast.area.under_attack",
landOwnerTown.getFormattedName(), worldCoord.toString(), attackingResident.getFormattedName()));
landOwnerTown.getFormattedName(), coordinates, attackingResident.getFormattedName()));
return true;
}

private static void flagPlacementChecks(final Block block) throws TownyException {
int seaLevel = block.getWorld().getSeaLevel();
int yLoc = block.getY();
int allowedDepth = FlagWarConfig.getDepthAllowance();
if (yLoc < seaLevel - allowedDepth) { // ensure flag is at or above sea-level - potentially configurable.
if (allowedDepth > 0) {
throw new TownyException(Translate.fromPrefixed("error.flag.below-sea-level-allowance", allowedDepth));
} else {
throw new TownyException(Translate.fromPrefixed("error.flag.below-sea-level"));
}
}

// Check 3 blocks up, ensure they valid blocks to overwrite.
final byte checkHeight = 5;
for (byte i = 1; i < checkHeight; i++) {
Block iBlock = block.getWorld().getBlockAt(block.getX(), block.getY() + i, block.getZ());
if (iBlock.isLiquid()) { // Submersion Check
throw new TownyException(Translate.fromPrefixed("error.flag.avoid-liquid"));
} else if (!iBlock.isEmpty()) { // General Space Check
throw new TownyException(Translate.fromPrefixed("error.flag.need-space-above"));
}
}

if (!block.getWorld().hasCeiling()) { // Ignore if natural ceiling for world
Block highestBlock = block.getWorld().getHighestBlockAt(block.getLocation());
if (highestBlock.getY() > block.getWorld().getMaxHeight() - checkHeight
&& yLoc < highestBlock.getY() - 1) { // Traditional check
throw new TownyException(Translate.fromPrefixed("error.flag.need-above-ground"));
}
}
}

private static boolean isThisPlotProtectedByNeighbours(final WorldCoord attackedCoord) {
UUID townUUID = attackedCoord.getTownOrNull().getUUID();
int friendlyPlots = 0;
Expand All @@ -569,13 +601,6 @@ private static boolean isThisPlotProtectedByNeighbours(final WorldCoord attacked
return friendlyPlots >= FlagWarConfig.numberOfNeighbouringPlotsToPreventAttack();
}

private static void checkFlagHeight(final Block block) throws TownyException {
int topY = block.getWorld().getHighestBlockYAt(block.getX(), block.getZ()) - 1;
if (block.getY() < topY) {
throw new TownyException(Translate.fromPrefixed("error.flag.need-above-ground"));
}
}

private static void setAttackerAsEnemy(final Nation defendingNation, final Nation attackingNation)
throws AlreadyRegisteredException {
if (!defendingNation.hasEnemy(attackingNation)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,14 @@ public static boolean isAffectedMaterial(final Material material) {
|| material == getBeaconWireFrameMaterial();
}

/**
* Query the accuracy level for coordinate-related broadcasts.
* @return Output of rules.flag_broadcast_accuracy.
*/
public static String getBroadcastAccuracy() {
return PLUGIN.getConfig().getString("rules.flag_broadcast_accuracy", "towny");
}

/**
* Returns a copy of the {@link Material} array making up the WarFlag's timer indicators.
* @return a clone of the Material array.
Expand Down Expand Up @@ -132,6 +140,13 @@ public static Material[] getCustomTimerBlocks() {
}
}

/**
* @return The configuration value for the depth, below a world's sea level, a flag may be placed.
*/
public static int getDepthAllowance() {
return PLUGIN.getConfig().getInt("rules.flag_depth_allowance");
}

/**
* Sets the editableMaterialsInWarZone.
*/
Expand Down
4 changes: 4 additions & 0 deletions src/main/resources/Translation_en_US.properties
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ error.cell-already-under-attack=&cThis area is already under attack by %s.
error.flag.insufficient-funds=&cYou require %s in order to place a warflag.
error.flag.max-flags-placed=&cYou can't attack more than %d areas at once.
error.flag.need-above-ground=&cMust place flag above ground.
error.flag.below-sea-level=&cFlags cannot be placed below sea level.
error.flag.below-sea-level-allowance=&cFlags can only be %d meters below sea level.
error.flag.avoid-liquid=&cFlags cannot be submersed in liquid.
error.flag.need-space-above=&cFlags require 4-high spaces to spawn.
error.insufficient-future-funds=&cYou need %s in the event you need to pay for %d %s(s).
error.nation-under-attack=&cYou cannot do this while a town in your nation is under attack!
error.need-at-least-1-claim=&cYou cannot attack while your town has 0 townblocks claimed.
Expand Down
4 changes: 4 additions & 0 deletions src/main/resources/Translation_es_MX.properties
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ error.cell-already-under-attack=&cThis area is already under attack by %s.
error.flag.insufficient-funds=&cYou require %s in order to place a warflag.
error.flag.max-flags-placed=&cYou can't attack more than %d areas at once.
error.flag.need-above-ground=&cMust place flag above ground.
error.flag.below-sea-level=&cFlags cannot be placed below sea level.
error.flag.below-sea-level-allowance=&cFlags can only be %d meters below sea level.
error.flag.avoid-liquid=&cFlags cannot be submersed in liquid.
error.flag.need-space-above=&cFlags require 4-high spaces to spawn.
error.insufficient-future-funds=&cYou need %s in the event you need to pay for %d %s(s).
error.nation-under-attack=&cYou cannot do this while a town in your nation is under attack!
error.need-at-least-1-claim=&cYou cannot attack while your town has 0 townblocks claimed.
Expand Down
4 changes: 4 additions & 0 deletions src/main/resources/Translation_fr_FR.properties
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ error.cell-already-under-attack=&cCette zone est déjà attaquée par %s.
error.flag.insufficient-funds=&cVous avez besoin de %s pour placer un drapeau de guerre.
error.flag.max-flags-placed=&cVous ne pouvez attaquer plus de %d zones à la fois.
error.flag.need-above-ground=&cUn drapeau doit être posé au sol.
error.flag.below-sea-level=&cFlags cannot be placed below sea level.
error.flag.below-sea-level-allowance=&cFlags can only be %d meters below sea level.
error.flag.avoid-liquid=&cFlags cannot be submersed in liquid.
error.flag.need-space-above=&cFlags require 4-high spaces to spawn.
error.insufficient-future-funds=&cVous avez besoin de %s durant l'événement pour payer %d %s(s).
error.nation-under-attack=&cVous ne pouvez faire cela lorsqu'une ville de votre nation est attaquée!
error.need-at-least-1-claim=&cVous ne pouvez pas attaquer une ville n'ayant aucun terrain.
Expand Down
4 changes: 4 additions & 0 deletions src/main/resources/Translation_ru_RU.properties
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ error.cell-already-under-attack=&cЭтот район уже атакован %s
error.flag.insufficient-funds=&cТребуется %s для того, чтобы поставить военный флаг..
error.flag.max-flags-placed=&cВы не можете атаковать сразу %d несколько областей.
error.flag.need-above-ground=&cФлаг должен быть установлен над землей.
error.flag.below-sea-level=&cFlags cannot be placed below sea level.
error.flag.below-sea-level-allowance=&cFlags can only be %d meters below sea level.
error.flag.avoid-liquid=&cFlags cannot be submersed in liquid.
error.flag.need-space-above=&cFlags require 4-high spaces to spawn.
error.insufficient-future-funds=&cВам нужно %s в случае, если вам нужно заплатить за %d %s(s).
error.nation-under-attack=&cВы не можете сделать это, пока город вашей страны находится под атакой!
error.need-at-least-1-claim=&cВы не можете атаковать, пока в вашем городе не заявлено 0 городских кварталов.
Expand Down
9 changes: 9 additions & 0 deletions src/main/resources/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,15 @@ rules:
# Are nations able to toggle on their neutrality, when FlagWar's allow_attacks is true?
nations_can_toggle_neutral: false

# Depth (meters) below sea-level a flag may be placed. (world-defined)
# Notice: Flags are still subject to submersion checks at this time.
flag_depth_allowance: 12

# Determines accuracy of location broadcasts.
# "towny" = Towny World Coordinates (`/towny map`)
# "precise" = X,Y,Z coordinates of the flag's base block.
flag_broadcast_accuracy: "towny"

player_limits:
min_online_in_town: 2
min_online_in_nation: 3
Expand Down

0 comments on commit ef578a6

Please sign in to comment.