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

Add MapTowny integration! #556

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,4 @@
- Special thanks to the servers *CCNET*, *DatBlock*, and *EarthPol*, who pioneered the use of the system, and have provided much valuable information, feedback, and bug reports.
- [Goosius1](https://github.com/Goosius1) was the maintainer of this repo for the TownyAdvanced org, until his retirement from *Minecraft* plugin development in October 2021.
- *SiegeWar* is now maintained by the TownyAdvanced org.
- "Fire" icon created by kosonicon
6 changes: 6 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,12 @@
<version>2.0.28-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>me.silverwolfg11</groupId>
<artifactId>maptowny-api</artifactId>
<version>2.0.0-BETA-2</version>
<scope>provided</scope>
</dependency>
</dependencies>

<build>
Expand Down
5 changes: 5 additions & 0 deletions src/main/java/com/gmail/goosius/siegewar/SiegeWar.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.gmail.goosius.siegewar;

import com.gmail.goosius.siegewar.enums.SiegeStatus;
import com.gmail.goosius.siegewar.integration.maptowny.MapTownyIntegration;
import com.gmail.goosius.siegewar.metadata.ResidentMetaDataController;
import com.gmail.goosius.siegewar.objects.Siege;
import com.gmail.goosius.siegewar.settings.SiegeWarSettings;
Expand Down Expand Up @@ -145,6 +146,10 @@ private void checkIntegrations() {
info("SiegeWar found Dynmap plugin, enabling Dynmap support.");
new DynmapIntegration(this);
}
if (getServer().getPluginManager().isPluginEnabled("MapTowny")) {
info("SiegeWar found the MapTowny plugin, enabling MapTowny support.");
new MapTownyIntegration(this);
}
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
package com.gmail.goosius.siegewar.integration.maptowny;

import com.gmail.goosius.siegewar.SiegeController;
import com.gmail.goosius.siegewar.SiegeWar;
import com.gmail.goosius.siegewar.enums.SiegeSide;
import com.gmail.goosius.siegewar.objects.BattleSession;
import com.gmail.goosius.siegewar.objects.Siege;
import com.gmail.goosius.siegewar.settings.Settings;
import com.palmergames.bukkit.towny.TownyEconomyHandler;
import com.palmergames.bukkit.towny.TownyUniverse;
import com.palmergames.bukkit.towny.object.TownyWorld;
import com.palmergames.bukkit.towny.object.Translation;
import com.palmergames.util.StringMgmt;
import me.silverwolfg11.maptowny.MapTownyPlugin;
import me.silverwolfg11.maptowny.objects.LayerOptions;
import me.silverwolfg11.maptowny.objects.MarkerOptions;
import me.silverwolfg11.maptowny.objects.Point2D;
import me.silverwolfg11.maptowny.platform.MapLayer;
import me.silverwolfg11.maptowny.platform.MapPlatform;
import me.silverwolfg11.maptowny.platform.MapWorld;
import org.apache.commons.lang.WordUtils;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.logging.Level;

public class MapTownyIntegration {

private final String SIEGE_MARKER_PREFIX = "siegewar_siege_";
private final String SIEGE_LAYER_PREFIX = "siegewar_layer_";
private final String PEACEFUL_BANNER_ICON_KEY = "siegewar_peaceful";
private final String BATTLE_BANNER_ICON_KEY = "siegewar_battle";

private final MapTownyPlugin mapTowny;
private final Map<String, MapLayer> worldLayers = new HashMap<>();
private boolean siegesRendered = false;

public MapTownyIntegration(SiegeWar plugin) {
this.mapTowny = (MapTownyPlugin) Bukkit.getPluginManager().getPlugin("MapTowny");

// Check if map towny found a valid web-map platform
if (mapTowny.getPlatform() == null) {
return;
}

// Register replacement handler
Bukkit.getPluginManager().registerEvents(new MapTownyReplacementsHandler(mapTowny), plugin);

// Re-render the sieges every time a new short time event triggers.
Bukkit.getPluginManager().registerEvents(new MapTownyShortTimeListener(this::displaySieges), plugin);

final String pluginName = plugin.getName();
// Run marker and layer setup on platform initialize
this.mapTowny.getPlatform().onInitialize(() -> {
registerIcons(plugin);
registerMarkerLayers(pluginName);
});
}

private BufferedImage readImage(final InputStream is, final String fileName) {
try {
return ImageIO.read(is);
} catch (IOException ex) {
String errorMsg = String.format("Error reading image from file '%s'...", fileName);
SiegeWar.getSiegeWar().getLogger().log(Level.SEVERE, errorMsg, ex);
return null;
}
}

private void registerIcons(final SiegeWar plugin) {
final MapPlatform platform = this.mapTowny.getPlatform();

if (!platform.hasIcon(PEACEFUL_BANNER_ICON_KEY)) {
String fileName = Settings.PEACEFUL_BANNER_FILE_NAME;
InputStream is = plugin.getResource(fileName);

BufferedImage img = readImage(is, fileName);
if (img != null) {
platform.registerIcon(PEACEFUL_BANNER_ICON_KEY, img, 16, 16);
}
}

if (!platform.hasIcon(BATTLE_BANNER_ICON_KEY)) {
String fileName = Settings.BATTLE_BANNER_FILE_NAME;
InputStream is = plugin.getResource(fileName);

BufferedImage img = readImage(is, fileName);
if (img != null) {
platform.registerIcon(BATTLE_BANNER_ICON_KEY, img, 16, 16);
}
}
}

private void registerMarkerLayers(String pluginName) {
MapPlatform platform = this.mapTowny.getPlatform();
LayerOptions layerOptions = new LayerOptions(pluginName, true, false, 10, 10);

// Register SiegeWar marker layer in all available towny worlds
for (TownyWorld townyWorld : TownyUniverse.getInstance().getTownyWorlds()) {
if(!townyWorld.isUsingTowny())
continue;

String worldName = townyWorld.getName();
World bukkitWorld = Bukkit.getWorld(worldName);

MapWorld mapWorld = bukkitWorld != null ? platform.getWorld(bukkitWorld) : null;

if (mapWorld == null)
continue;

MapLayer mapLayer = mapWorld.registerLayer(SIEGE_LAYER_PREFIX + worldName, layerOptions);
worldLayers.put(worldName, mapLayer);
}
}

private String getSiegeMarkerKey(UUID townUUID) {
return "siegewar_siege_" + townUUID.toString();
}

void displaySieges() {
// Avoid attempting to remove markers if no sieges were rendered
if (siegesRendered) {
// Remove all siege markers before re-rendering all of them
for (Map.Entry<String, MapLayer> worldLayerEntry : worldLayers.entrySet()) {
final MapLayer mapLayer = worldLayerEntry.getValue();
mapLayer.removeMarkers(s -> s.startsWith(SIEGE_MARKER_PREFIX));
}

siegesRendered = false;
}

// Add all active siege markers
for (Siege siege : SiegeController.getSieges()) {

String name = Translation.of("dynmap_siege_title", siege.getAttackerNameForDisplay(), siege.getDefenderNameForDisplay());
try {
if (siege.getStatus().isActive()) {
Location siegeLoc = siege.getFlagLocation();
final String siegeWorldName = siegeLoc.getWorld().getName();

MapLayer mapLayer = worldLayers.get(siegeWorldName);

if (mapLayer == null)
continue;

//If siege is dormant, show the fire icon, otherwise show the crossed swords icon.
String iconKey;
if (isSiegeDormant(siege)) {
iconKey = PEACEFUL_BANNER_ICON_KEY;
} else {
iconKey = BATTLE_BANNER_ICON_KEY;
}

List<String> lines = new ArrayList<>();
lines.add(Translation.of("dynmap_siege_town", siege.getTown().getName()));
lines.add(Translation.of("dynmap_siege_type", siege.getSiegeType().getName()));
lines.add(Translation.of("dynmap_siege_balance", siege.getSiegeBalance()));
lines.add(Translation.of("dynmap_siege_time_left", siege.getTimeRemaining()));
if(TownyEconomyHandler.isActive()) {
lines.add(Translation.of("dynmap_siege_war_chest", TownyEconomyHandler.getFormattedBalance(siege.getWarChestAmount())));
}
lines.add(Translation.of("dynmap_siege_banner_control",
WordUtils.capitalizeFully(siege.getBannerControllingSide().name())
+ (siege.getBannerControllingSide() == SiegeSide.NOBODY ? "" : " (" + siege.getBannerControllingResidents().size() + ")")));
lines.add(Translation.of("dynmap_siege_battle_points", siege.getFormattedAttackerBattlePoints(), siege.getFormattedDefenderBattlePoints()));
lines.add(Translation.of("dynmap_siege_battle_time_left", siege.getFormattedBattleTimeRemaining()));

String desc = "<b>" + name + "</b><hr>" + StringMgmt.join(lines, "<br>");

double siegeX = siegeLoc.getX();
double siegeZ = siegeLoc.getZ();
final UUID townUUID = siege.getTown().getUUID();
String siegeMarkerId = getSiegeMarkerKey(townUUID);

MarkerOptions markerOptions = MarkerOptions.builder()
.name(name)
.clickTooltip(desc)
.hoverTooltip(desc)
.build();

Point2D iconLoc = Point2D.of(siegeX, siegeZ);
mapLayer.addIconMarker(siegeMarkerId, iconKey, iconLoc, 16, 16, markerOptions);
siegesRendered = true;
}
} catch (Exception ex) {
SiegeWar.severe("Problem adding siege marker for siege: " + name);
ex.printStackTrace();
}
}

}

/**
* A siege is dormant if there is no significant activity there (e.g. kills, banner control).
*
* This state is represented by a fire icon on the map.
* If the battle becomes active, the icon changes to crossed-swords.
*
* @return true if siege is dormant
*/
private boolean isSiegeDormant(Siege siege) {
return !BattleSession.getBattleSession().isActive()
|| (siege.getAttackerBattlePoints() == 0
&& siege.getDefenderBattlePoints() == 0
&& siege.getBannerControllingSide() == SiegeSide.NOBODY
&& siege.getBannerControlSessions().size() == 0);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.gmail.goosius.siegewar.integration.maptowny;

import com.gmail.goosius.siegewar.TownOccupationController;
import me.silverwolfg11.maptowny.MapTownyPlugin;
import me.silverwolfg11.maptowny.events.MapReloadEvent;
import me.silverwolfg11.maptowny.managers.LayerManager;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;

public class MapTownyReplacementsHandler implements Listener {

private final MapTownyPlugin mapTowny;

public MapTownyReplacementsHandler(MapTownyPlugin mapTowny) {
this.mapTowny = mapTowny;
registerReplacements();
}

private void registerReplacements() {
LayerManager layerManager = mapTowny.getLayerManager();

if (layerManager == null)
return;

layerManager.registerReplacement("%occupier%", town ->
TownOccupationController.isTownOccupied(town) ?
TownOccupationController.getTownOccupier(town).getName() : ""
);
}

// Re-register replacements when maptowny reloads
@EventHandler
void onMapTownyReload(MapReloadEvent event) {
registerReplacements();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.gmail.goosius.siegewar.integration.maptowny;

import com.palmergames.bukkit.towny.event.time.NewShortTimeEvent;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;

public class MapTownyShortTimeListener implements Listener {

private final Runnable renderSieges;

public MapTownyShortTimeListener(Runnable renderSieges) {
this.renderSieges = renderSieges;
}

@EventHandler
public void onNewShortTime(NewShortTimeEvent event) {
this.renderSieges.run();
Copy link
Collaborator

@Goosius1 Goosius1 May 1, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚧

  • Have I missed something, or is threading unnecessary here?
  • Couldn't we just do something un-threaded like: SiegeWar.getMapTownyIntegration().displaySieges() ?

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public class Settings {
private static CommentedConfiguration config, newConfig;
private static File battleIconFile;
public static final String BATTLE_BANNER_FILE_NAME = "crossedswords.png";
public static final String PEACEFUL_BANNER_FILE_NAME = "fire.png";

public static boolean loadSettingsAndLang() {
SiegeWar sw = SiegeWar.getSiegeWar();
Expand Down
Binary file added src/main/resources/fire.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion src/main/resources/plugin.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ author: [Goosius,LlmDl]
website: 'townyadvanced.github.io'
prefix: ${project.artifactId}
depend: [Towny]
softdepend: [TownyCultures, dynmap, Cannons, Dynmap-Towny]
softdepend: [TownyCultures, dynmap, Cannons, Dynmap-Towny, MapTowny]

description: A war system made by Goosius for Towny.

Expand Down