Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Siege Lore Feature - Record of Siege data and outcome on the banner item #909

Merged
merged 94 commits into from
May 14, 2024
Merged
Show file tree
Hide file tree
Changes from 71 commits
Commits
Show all changes
94 commits
Select commit Hold shift + click to select a range
793831e
Config nodes for Maximum and Minimum banner place distance
lexiccn Apr 19, 2024
1ab63b6
Add SiegeWarBlockUtil#getSurroundingTownBlocks
lexiccn Apr 19, 2024
51eab37
Change Minimum behaviour so Max - Min is amount of usable townblocks
lexiccn Apr 19, 2024
2d8a6ea
Change getSurroundingTownBlocks to not exclude a radius
lexiccn Apr 19, 2024
da255d5
Use Min and Max distances to evaluate townblock when banner placed
lexiccn Apr 19, 2024
50eff4e
Add cardinal town block check back
lexiccn Apr 19, 2024
0aa166f
Fix TODO message...
lexiccn Apr 19, 2024
e987416
Add string for below minimum distance
lexiccn Apr 19, 2024
32ad6dc
Change SiegeWarSettings to return 0 if min is 0 or below, not 1
lexiccn Apr 19, 2024
489b9e7
Give user an error message if banner has town blocks in the excluded …
lexiccn Apr 19, 2024
7fe822e
Slightly improve wording to try to make clearer that the minimum is e…
lexiccn Apr 19, 2024
f859fe2
Re-add exclusion radius to getSurrounding to optimise
lexiccn Apr 21, 2024
2231805
Check exclusion radius first, then check valid while ignoring exclusion
lexiccn Apr 21, 2024
ea13a01
Clarify that radius is measured in townblocks
lexiccn Apr 21, 2024
4605802
Return empty list if minimum is bigger or the same as maximum radius
lexiccn Apr 21, 2024
871c1c3
Remove plan unrelated to main feature
lexiccn Apr 21, 2024
aee6470
Bump Towny dependency to 0.100.2.0 for Java 1.8 compiling
lexiccn Apr 21, 2024
6a98ac2
Slightly bump recommended maximum distance
lexiccn Apr 21, 2024
6c621f2
Add SiegeWarBannerLoreUtil with start/end function
lexiccn Apr 21, 2024
c6ecf2b
Rename methods and set siege name
lexiccn Apr 21, 2024
0eac9aa
Add config node siege_lore
lexiccn Apr 21, 2024
cc2a88c
Merge branch 'master' into banner_place_distance_override
lexiccn Apr 21, 2024
c22429f
Check config node before setting banner PDC
lexiccn Apr 21, 2024
b95243a
Shorten to SiegeWarLoreUtil as it could be used for non-banners
lexiccn Apr 21, 2024
060f9ae
Add editable string formats
lexiccn Apr 21, 2024
b758b5d
Redo LoreUtil to directly store the lore lines, rather than information
lexiccn Apr 21, 2024
6197ea1
Create LoreListener and register it
lexiccn Apr 21, 2024
8d234bf
Add missing format argument
lexiccn Apr 21, 2024
1a100f2
Set item meta and stack back
lexiccn Apr 21, 2024
9522f63
Use shortened names for banner name
lexiccn Apr 21, 2024
b083fb6
Use Defending Nation if possible, except in banner name to ensure Tow…
lexiccn Apr 21, 2024
cbb9973
Change X vs Y name to Siege of Z
lexiccn Apr 22, 2024
b2678fe
Reformat strings
lexiccn Apr 22, 2024
cae761d
Use generic ItemMeta instead of BannerMeta
lexiccn Apr 22, 2024
4fb2a1c
Replace existing lore, not append
lexiccn Apr 22, 2024
9c6fee8
Restructure strings for further modularity...
lexiccn Apr 22, 2024
73a13cb
Translatable placeholder for Unknown
lexiccn Apr 22, 2024
0e6e482
Rename siege_lore_banner_points to siege_lore_secondary_value
lexiccn Apr 22, 2024
4307ab0
Add %s directly to banner_type string
lexiccn Apr 22, 2024
042ea8a
Rewrite lore util with new translation keys for shield and banners
lexiccn Apr 22, 2024
51e06ee
Update method calls
lexiccn Apr 22, 2024
7a82c58
Update lore listener to use new methods
lexiccn Apr 22, 2024
d72706d
Swap color and secondary so it is consistent
lexiccn Apr 22, 2024
3c1396c
Chat lore strings
lexiccn Apr 22, 2024
eef33e1
Replace missed placeholder with %s
lexiccn Apr 22, 2024
acc4842
Rename and split strings
lexiccn Apr 22, 2024
b8f8aea
Getter methods for the values
lexiccn Apr 22, 2024
1bc1f12
String for unknown victor
lexiccn Apr 22, 2024
b01f533
Rewrite strings to ensure colours correct
lexiccn Apr 22, 2024
6cfcf76
Minor formatting
lexiccn Apr 22, 2024
d1fc32d
Mention the opposition in chat lore
lexiccn Apr 22, 2024
7de2cee
Generic strings when the winner isn't known
lexiccn Apr 22, 2024
700df69
Add missing spaces
lexiccn Apr 22, 2024
2148ff4
Listener for chat lore
lexiccn Apr 22, 2024
dda0c30
Error message for starting siege
lexiccn Apr 22, 2024
70018bf
Ignore if not a right click with main hand
lexiccn Apr 22, 2024
d6a0c69
More chat lore changes
lexiccn Apr 22, 2024
5f6e302
Remove periods after dates
lexiccn Apr 22, 2024
719069a
Fiddle with priorities to fix cancelling the siege
lexiccn Apr 22, 2024
4300053
Remove unused imports
lexiccn Apr 22, 2024
6cfaec5
Action and hand check
lexiccn Apr 23, 2024
cae311b
Move chat message generator to LoreUtil
lexiccn Apr 23, 2024
3b18817
Cancel interact if Lore is disabled
lexiccn Apr 23, 2024
ec1802d
Cancel craft if lore is disabled
lexiccn Apr 23, 2024
f93575e
Format this like other EventHandlers
lexiccn Apr 23, 2024
6ed8d43
Listen to SiegeStart/End instead of forcing it into code
lexiccn Apr 23, 2024
8dc180d
Rename some Util methods so they start with "banner" or "shield"
lexiccn Apr 23, 2024
239719f
Change chat lore keys
lexiccn Apr 23, 2024
d418b8e
Formatted and raw PDC methods
lexiccn Apr 23, 2024
d8944bc
Remove a debug logger that somehow slipped through
lexiccn Apr 23, 2024
e0c729f
And the import for it..
lexiccn Apr 23, 2024
d6132ca
Fix two possible NPEs
lexiccn Apr 23, 2024
f8f6cb0
Change a bunch of translations to color methods
lexiccn Apr 23, 2024
d4e6d2a
More logical translation key names
lexiccn Apr 23, 2024
e3fbef1
Update uses and NamespacedKeys to be generic (not use "banner")
lexiccn Apr 23, 2024
0f7f2e4
Fix a missed string key
lexiccn Apr 23, 2024
e0f4fc2
Undo IDE wildcard imports (thank you intellij)
lexiccn Apr 23, 2024
3245491
Note about shields in config
lexiccn Apr 23, 2024
4ed6399
Private LoreUtil color methods
lexiccn Apr 23, 2024
994f12e
Private LoreUtil getSiege methods
lexiccn Apr 23, 2024
255cefc
Use MONITOR for SiegeStart and End
lexiccn Apr 23, 2024
5d1298e
Comment LOW priority onPlaceBlock
lexiccn Apr 23, 2024
242068d
Change LORE PDC key
lexiccn Apr 23, 2024
7d8db2e
Improve listener with new methods
lexiccn Apr 23, 2024
acd6183
Private lots of util methods, take ItemStack and BlockState instead o…
lexiccn Apr 23, 2024
3af148f
Copy data from Holder to Banner/Shield
lexiccn Apr 23, 2024
65f2c68
Private more methods and fields
lexiccn Apr 23, 2024
88d8004
Remove an unused import
lexiccn Apr 23, 2024
d1b1ffa
Fix inverted check
lexiccn Apr 27, 2024
26368f2
Better? name for copyData method
lexiccn Apr 27, 2024
3c5a126
Better names for bannerSiegeStart & bannerSiegeEnd
lexiccn Apr 27, 2024
9c5f0d6
JavaDoc for onPlaceBlock
lexiccn Apr 27, 2024
79f2c30
Fix onDropBanner BlockState getter
lexiccn Apr 27, 2024
d7c659e
Add to onPlaceBlock javadoc
lexiccn Apr 27, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,9 @@
import com.gmail.goosius.siegewar.events.SiegeCampStartEvent;
import com.gmail.goosius.siegewar.events.SiegeWarStartEvent;
import com.gmail.goosius.siegewar.settings.SiegeWarSettings;
import com.gmail.goosius.siegewar.utils.DataCleanupUtil;
import com.gmail.goosius.siegewar.utils.*;
lexiccn marked this conversation as resolved.
Show resolved Hide resolved
import com.gmail.goosius.siegewar.timeractions.AttackerTimedWin;
import com.gmail.goosius.siegewar.timeractions.DefenderTimedWin;
import com.gmail.goosius.siegewar.utils.SiegeCampUtil;
import com.gmail.goosius.siegewar.utils.SiegeWarDistanceUtil;
import com.gmail.goosius.siegewar.utils.SiegeWarNationUtil;
import com.gmail.goosius.siegewar.utils.SiegeWarSiegeCompletionUtil;
import com.palmergames.bukkit.towny.TownyEconomyHandler;
import com.palmergames.bukkit.towny.TownyMessaging;
import com.palmergames.bukkit.towny.object.Government;
Expand All @@ -40,7 +36,6 @@
import com.gmail.goosius.siegewar.metadata.SiegeMetaDataController;
import com.gmail.goosius.siegewar.objects.Siege;
import com.gmail.goosius.siegewar.objects.SiegeCamp;
import com.gmail.goosius.siegewar.utils.SiegeWarMoneyUtil;
import com.palmergames.bukkit.towny.TownyAPI;
import com.palmergames.bukkit.towny.TownyUniverse;
import com.palmergames.bukkit.towny.exceptions.TownyException;
Expand Down
12 changes: 2 additions & 10 deletions src/main/java/com/gmail/goosius/siegewar/SiegeWar.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.gmail.goosius.siegewar;

import com.gmail.goosius.siegewar.listeners.SiegeWarTownyChatEventListener;
import com.gmail.goosius.siegewar.listeners.*;
lexiccn marked this conversation as resolved.
Show resolved Hide resolved
import com.gmail.goosius.siegewar.settings.SiegeWarSettings;
import com.gmail.goosius.siegewar.utils.DataCleanupUtil;

Expand All @@ -25,15 +25,6 @@
import com.gmail.goosius.siegewar.command.SiegeWarNationSetOccupationTaxAddonCommand;
import com.gmail.goosius.siegewar.hud.SiegeHUDManager;
import com.gmail.goosius.siegewar.integration.dynmap.DynmapIntegration;
import com.gmail.goosius.siegewar.listeners.SiegeWarActionListener;
import com.gmail.goosius.siegewar.listeners.SiegeWarBukkitEventListener;
import com.gmail.goosius.siegewar.listeners.SiegeWarNationEventListener;
import com.gmail.goosius.siegewar.listeners.SiegeWarPlotEventListener;
import com.gmail.goosius.siegewar.listeners.SiegeWarSafeModeListener;
import com.gmail.goosius.siegewar.listeners.SiegeWarSelfListener;
import com.gmail.goosius.siegewar.listeners.SiegeWarStatusScreenListener;
import com.gmail.goosius.siegewar.listeners.SiegeWarTownEventListener;
import com.gmail.goosius.siegewar.listeners.SiegeWarTownyEventListener;

import java.io.File;
import java.nio.file.Files;
Expand Down Expand Up @@ -174,6 +165,7 @@ private boolean registerListeners() {
pm.registerEvents(new SiegeWarPlotEventListener(this), this);
pm.registerEvents(new SiegeWarStatusScreenListener(), this);
pm.registerEvents(new SiegeWarSelfListener(), this);
pm.registerEvents(new SiegeWarLoreListener(), this);
if (getServer().getPluginManager().isPluginEnabled("TownyChat")) {
info("SiegeWar found TownyChat plugin, enabling TownyChat integration.");
pm.registerEvents(new SiegeWarTownyChatEventListener(), this);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
package com.gmail.goosius.siegewar.listeners;

import com.gmail.goosius.siegewar.Messaging;
import com.gmail.goosius.siegewar.events.PreSiegeCampEvent;
import com.gmail.goosius.siegewar.events.SiegeEndEvent;
import com.gmail.goosius.siegewar.events.SiegeWarStartEvent;
import com.gmail.goosius.siegewar.settings.SiegeWarSettings;
import com.gmail.goosius.siegewar.utils.SiegeWarLoreUtil;
import com.palmergames.bukkit.towny.object.Translation;
import org.bukkit.Material;
import org.bukkit.Tag;
import org.bukkit.block.Banner;
import org.bukkit.entity.Item;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.Action;
import org.bukkit.event.block.BlockDropItemEvent;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.inventory.PrepareItemCraftEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.BannerMeta;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.persistence.PersistentDataHolder;

import java.util.Arrays;

/**
*
* @author lexiccn
*
*/
public class SiegeWarLoreListener implements Listener {

@EventHandler(priority = EventPriority.LOWEST)
LlmDl marked this conversation as resolved.
Show resolved Hide resolved
public void onSiegeStart(SiegeWarStartEvent event) {
if (!SiegeWarSettings.isSiegeLoreEnabled()) return;

//Set name, type, attacker, defender, start time
SiegeWarLoreUtil.bannerSiegeStart(event.getSiege());
}

@EventHandler(priority = EventPriority.LOWEST)
LlmDl marked this conversation as resolved.
Show resolved Hide resolved
public void onSiegeEnd(SiegeEndEvent event) {
if (!SiegeWarSettings.isSiegeLoreEnabled()) return;

//Set outcome, winner, points, end time
SiegeWarLoreUtil.bannerSiegeEnd(event.getSiege());
}

@EventHandler
public void onInteractBanner(PlayerInteractEvent event) {
if (!SiegeWarSettings.isSiegeLoreEnabled()) return;

PersistentDataContainer container;
if (event.hasBlock()) {
if (event.getHand() != EquipmentSlot.HAND) return;
if (event.getAction() != Action.RIGHT_CLICK_BLOCK) return;
if (event.getClickedBlock().isEmpty()) return;
if (!Tag.BANNERS.isTagged(event.getClickedBlock().getType())) return;
if (!(event.getClickedBlock().getState() instanceof PersistentDataHolder)) return;
PersistentDataHolder holder = (PersistentDataHolder) event.getClickedBlock().getState();
container = holder.getPersistentDataContainer();
} else if (event.hasItem()) {
if (event.getHand() != EquipmentSlot.HAND) return;
if (event.getAction() != Action.RIGHT_CLICK_AIR) return;
if (!Tag.BANNERS.isTagged(event.getMaterial())) return;
ItemStack item = event.getItem();
if (!item.hasItemMeta()) return;
container = item.getItemMeta().getPersistentDataContainer();
} else return;

if (!SiegeWarLoreUtil.hasLoreKey(container)) return;

Messaging.sendMsg(event.getPlayer(), SiegeWarLoreUtil.bannerChat(container));
}

@EventHandler
public void onPrepareCraft(PrepareItemCraftEvent event) {
if (!SiegeWarSettings.isSiegeLoreEnabled()) return;

ItemStack resultItem = event.getInventory().getResult();
if (resultItem == null) return;
if (resultItem.getType() != Material.SHIELD) return;

ItemStack bannerItem = Arrays.stream(event.getInventory().getMatrix()).filter(itemStack -> {
if (itemStack == null) return false;
if (itemStack.getItemMeta() instanceof BannerMeta) {
return SiegeWarLoreUtil.hasLoreKey(itemStack.getItemMeta().getPersistentDataContainer());
}
return false;
}).findFirst().orElse(null);
if (bannerItem == null) return;

ItemMeta resultMeta = resultItem.getItemMeta();

SiegeWarLoreUtil.bannerCopyData(bannerItem.getItemMeta().getPersistentDataContainer(), resultMeta.getPersistentDataContainer());
SiegeWarLoreUtil.shieldItem(resultMeta, bannerItem.getItemMeta().getPersistentDataContainer());

resultItem.setItemMeta(resultMeta);
}

@EventHandler(ignoreCancelled = true)
public void onTryStartSiege(PreSiegeCampEvent event) {
if (!SiegeWarSettings.isSiegeLoreEnabled()) return;

if (!(event.getFlag().getState() instanceof Banner)) return;
Banner flag = (Banner)event.getFlag().getState();

if (!SiegeWarLoreUtil.hasLoreKey(flag.getPersistentDataContainer())) return;

event.setCancelled(true);
event.setCancellationMsg(Translation.of("siege_lore_error_banner_cannot_be_used"));
}

@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
lexiccn marked this conversation as resolved.
Show resolved Hide resolved
public void onPlaceBlock(BlockPlaceEvent event) {
if (!SiegeWarSettings.isSiegeLoreEnabled()) return;

if (!(event.getItemInHand().getItemMeta() instanceof BannerMeta)) return;
if (!(event.getBlock().getState() instanceof Banner)) return;
Banner state = (Banner)event.getBlock().getState();
BannerMeta meta = (BannerMeta)event.getItemInHand().getItemMeta();

if (!SiegeWarLoreUtil.hasLoreKey(meta.getPersistentDataContainer())) return;

SiegeWarLoreUtil.bannerCopyData(meta.getPersistentDataContainer(), state.getPersistentDataContainer());

state.update();
}

@EventHandler(ignoreCancelled = true)
public void onDropBanner(BlockDropItemEvent event) {
if (!SiegeWarSettings.isSiegeLoreEnabled()) return;

if (event.getItems().isEmpty()) return;
Item item = event.getItems().get(0);
if (!(item.getItemStack().getItemMeta() instanceof BannerMeta)) return;
if (!(event.getBlockState() instanceof Banner)) return;
Banner state = (Banner)event.getBlockState();
BannerMeta meta = (BannerMeta)item.getItemStack().getItemMeta();

if (!SiegeWarLoreUtil.hasLoreKey(state.getPersistentDataContainer())) return;

ItemStack stack = item.getItemStack();

SiegeWarLoreUtil.bannerCopyData(state.getPersistentDataContainer(), meta.getPersistentDataContainer());
SiegeWarLoreUtil.bannerItem(meta, state.getPersistentDataContainer());

stack.setItemMeta(meta);
item.setItemStack(stack);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1161,7 +1161,25 @@ public enum ConfigNodes {
"# If this value is true, then the Battle Commander feature is enabled.",
"# When a battle sessions starts, then for each siege, one player from each side may be designated as the Battle Commander.",
"# To qualify as a battle commander, a player must be an official participant with general or king rank, and be online and in the Siege-Zone.",
"# If one side has a battle commander, then any member can run /sw spawn <town> to spawn on the commander.");
"# If one side has a battle commander, then any member can run /sw spawn <town> to spawn on the commander."),
SIEGE_LORE(
"siege_lore",
"",
"",
"",
"############################################################",
"# +------------------------------------------------------+ #",
"# | SIEGE LORE | #",
"# +------------------------------------------------------+ #",
"############################################################",
""),
SIEGE_LORE_ENABLED(
"siege_lore.enabled",
"true",
"",
"# If this value is true, then the Siege Lore feature is enabled.",
"# When a banner is broken after a siege has ended, it will drop with a name and lore set to display info about the siege.",
"# Banners dropped from this feature can be placed and broken without losing lore, but can not be used to begin a new siege.");
lexiccn marked this conversation as resolved.
Show resolved Hide resolved
private final String Root;
private final String Default;
private String[] comments;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -620,6 +620,10 @@ public static boolean isBattleCommandersEnabled() {
return Settings.getBoolean(ConfigNodes.BATTLE_COMMANDERS_ENABLED);
}

public static boolean isSiegeLoreEnabled() {
return Settings.getBoolean(ConfigNodes.SIEGE_LORE_ENABLED);
}

public static String getDynmapLayerName() {
return Settings.getString(ConfigNodes.WAR_SIEGE_DYNMAP_LAYER_NAME);
}
Expand Down
Loading