Skip to content
Permalink
Browse files

Implement Sentry Importer (#22)

* Implement basic Sentry -> Sentinel imports

 * Moved some constants into the SentinelTrait class so they can be used in range checks during import.
 * Added Sentry as a dependency because that's the easiest way to get at the data. Let Sentry load it, and then read it right out of Sentry's objects
 * Sentry's can now be imported using a command

Caveats:
 * Weapons are not modified, so if a weapon created a specific attack in Sentry, there is no gurantee the same attack will be used in Sentinel
 * Warnings/Greetings are not imported
 * Anything not yet supported by sentinel is not imported
   - Guarding non players
   - Various integration targets (towns/nations/factions)

* Switch files from tabs to spaces to respect project whitespace preference.

* Several minor fixes to Sentry Import

 * Correct permission checked
 * Add checked permission to plugin.yml
 * Reference latest version of sentry
  • Loading branch information...
wd40bomber7 authored and mcmonkey4eva committed Apr 25, 2016
1 parent 20a2bd5 commit 71e8dd028f48063bb75696ead1c9f39b334556dc
@@ -15,6 +15,7 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<craftbukkit.version>1.9-R0.1-SNAPSHOT</craftbukkit.version>
<citizens.version>2.0.17-SNAPSHOT</citizens.version>
<sentry.version>1.9.0</sentry.version>
<BUILD_NUMBER>Unknown</BUILD_NUMBER>
</properties>

@@ -57,6 +58,13 @@
<version>1.5.6</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.aufdemrand</groupId>
<artifactId>sentry</artifactId>
<version>${sentry.version}</version>
<type>jar</type>
<scope>provided</scope>
</dependency>
</dependencies>

<ciManagement>
@@ -142,7 +142,19 @@ public SentinelTrait getSentinelFor(CommandSender sender) {
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
String arg0 = args.length > 0 ? args[0].toLowerCase(): "help";
SentinelTrait sentinel = getSentinelFor(sender);
if (sentinel == null && !arg0.equals("help")) {
if (arg0.equals("sentryimport") && sender.hasPermission("sentinel.sentryimport")) {
if (Bukkit.getServer().getPluginManager().getPlugin("Sentry") == null) {
sender.sendMessage(prefixBad + "Sentry plugin must be installed to perform import!");
}
else {
sender.sendMessage(prefixGood + "Converting all npcs from sentry to sentinel...");
int imported = SentryImport.PerformImport();
sender.sendMessage(prefixGood + "Imported " + imported + " sentries. You may now restart and remove the sentry plugin.");
}
return true;
}
// All commands below this point will require a sentinel to be selected
else if (sentinel == null && !arg0.equals("help")) {
sender.sendMessage(prefixBad + "Must have an NPC selected!");
return true;
}
@@ -458,7 +470,7 @@ else if (arg0.equals("armor") && sender.hasPermission("sentinel.armor") && args.
else if (arg0.equals("health") && sender.hasPermission("sentinel.health") && args.length > 1) {
try {
Double d = Double.valueOf(args[1]);
if (d <= 200) {
if ((d >= SentinelTrait.healthMin) && (d <= SentinelTrait.healthMax)) {
sentinel.setHealth(d);
sender.sendMessage(prefixGood + "Health set!");
}
@@ -474,7 +486,7 @@ else if (arg0.equals("health") && sender.hasPermission("sentinel.health") && arg
else if (arg0.equals("attackrate") && sender.hasPermission("sentinel.attackrate") && args.length > 1) {
try {
int d = Integer.valueOf(args[1]);
if (d >= 10 && d <= 2000) {
if (d >= SentinelTrait.attackRateMin && d <= SentinelTrait.attackRateMax) {
sentinel.attackRate = d;
sender.sendMessage(prefixGood + "Attack rate set!");
}
@@ -490,7 +502,7 @@ else if (arg0.equals("attackrate") && sender.hasPermission("sentinel.attackrate"
else if (arg0.equals("healrate") && sender.hasPermission("sentinel.healrate") && args.length > 1) {
try {
int d = Integer.valueOf(args[1]);
if (d >= 0 && d <= 2000) {
if (d >= SentinelTrait.healRateMin && d <= SentinelTrait.healRateMax) {
sentinel.healRate = d;
sender.sendMessage(prefixGood + "Heal rate set!");
}
@@ -113,6 +113,9 @@ public SentinelTrait() {
@Persist("armor")
public double armor = -1.0;

public static final int healthMin = 1;
public static final int healthMax = 2000;

@Persist("health")
public double health = 20.0;

@@ -128,9 +131,15 @@ public SentinelTrait() {
@Persist("fightback")
public boolean fightback = true;

public static final int attackRateMin = 10;
public static final int attackRateMax = 2000;

@Persist("attackRate")
public int attackRate = 30;

public static final int healRateMin = 0;
public static final int healRateMax = 2000;

@Persist("healRate")
public int healRate = 30;

@@ -0,0 +1,216 @@
package org.mcmonkey.sentinel;

import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.event.Listener;

import net.aufdemrand.sentry.SentryInstance;
import net.aufdemrand.sentry.SentryTrait;
import net.citizensnpcs.api.CitizensAPI;
import net.citizensnpcs.api.npc.NPC;

public class SentryImport implements Listener {

// Converts sentries to sentinels. Returns the number of NPCs converted
@SuppressWarnings("deprecation")
public static int PerformImport() {
int convertedCount = 0;
for (NPC npc : CitizensAPI.getNPCRegistry()) {
if (!npc.hasTrait(SentryTrait.class)) {
continue;
}

SentryInstance sentry = npc.getTrait(SentryTrait.class).getInstance();
// This can happen if citizens was reloaded
if (sentry == null) {
continue;
}
convertedCount++;

// Now we've got our instance, lets create the sentinel trait instead
npc.removeTrait(SentryTrait.class);
if (!npc.hasTrait(SentinelTrait.class)) {
npc.addTrait(SentinelTrait.class);
}
SentinelTrait sentinel = npc.getTrait(SentinelTrait.class);

// Import time, import everything as best as we can
sentinel.armor = sentry.Armor;
sentinel.attackRate = (int)Math.ceil(sentry.AttackRateSeconds * 20);
if (sentinel.attackRate < SentinelTrait.attackRateMin) {
sentinel.attackRate = SentinelTrait.attackRateMin;
}
else if (sentinel.attackRate > SentinelTrait.attackRateMax) {
sentinel.attackRate = SentinelTrait.attackRateMax;
}
sentinel.chaseRange = sentry.sentryRange;
sentinel.closeChase = true;
sentinel.damage = sentry.Strength;
sentinel.enemyDrops = sentry.KillsDropInventory;

// Import targets
for (String t: sentry.validTargets){
if (t.contains("ENTITY:ALL")) {
sentinel.targets.add(SentinelTarget.MOBS);
sentinel.targets.add(SentinelTarget.PLAYERS);
sentinel.targets.add(SentinelTarget.NPCS);
}
else if(t.contains("ENTITY:MONSTER")) {
sentinel.targets.add(SentinelTarget.MONSTERS);
}
else if(t.contains("ENTITY:PLAYER")) {
sentinel.targets.add(SentinelTarget.PLAYERS);
}
else if(t.contains("ENTITY:NPC")) {
sentinel.targets.add(SentinelTarget.NPCS);
}
else{
String[] sections = t.split(":");
if (sections.length != 2) {
// Invalid target identifier?
continue;
}
// Sentry was spacing tolerant, so we should be too.
sections[0] = sections[0].trim();
sections[1] = sections[1].trim();
if(sections[0].equals("NPC")) {
sentinel.npcNameTargets.add(sections[1]);
}
else if (sections[0].equals("GROUP")) {
sentinel.groupTargets.add(sections[1]);
}
else if(sections[0].equals("PLAYER")) {
sentinel.playerNameTargets.add(sections[1]);
}
else if(sections[0].equals("ENTITY")) {
SentinelTarget target = SentinelTarget.forName(sections[1]);
if (target != null) {
sentinel.targets.add(target);
}
}
/*
These target specifiers are not implemented in Sentinel yet and so can't be imported
else if (sections[0].equals("EVENT"))
else if (sections[0].equals("FACTION"))
else if (sections[0].equals("FACTIONENEMIES"))
else if (sections[0].equals("TOWN"))
else if (sections[0].equals("NATIONENEMIES"))
else if (sections[0].equals("NATION"))
else if (sections[0].equals("WARTEAM"))
else if (sections[0].equals("TEAM"))
else if (sections[0].equals("CLAN"))
*/
}
}
// Import ignores, remove default ignore OWNER
sentinel.ignores.remove(SentinelTarget.OWNER);
for (String t: sentry.ignoreTargets){
if (t.contains("ENTITY:ALL")) {
sentinel.ignores.add(SentinelTarget.MOBS);
sentinel.ignores.add(SentinelTarget.PLAYERS);
sentinel.ignores.add(SentinelTarget.NPCS);
}
else if(t.contains("ENTITY:MONSTER")) {
sentinel.ignores.add(SentinelTarget.MONSTERS);
}
else if(t.contains("ENTITY:PLAYER")) {
sentinel.ignores.add(SentinelTarget.PLAYERS);
}
else if(t.contains("ENTITY:NPC")) {
sentinel.ignores.add(SentinelTarget.NPCS);
}
else if(t.contains("ENTITY:OWNER")) {
sentinel.ignores.add(SentinelTarget.OWNER);
}
else{
String[] sections = t.split(":");
if (sections.length != 2) {
// Invalid target identifier?
continue;
}
// Sentry was spacing tolerant, so we should be too.
sections[0] = sections[0].trim();
sections[1] = sections[1].trim();
if(sections[0].equals("NPC")) {
sentinel.npcNameIgnores.add(sections[1]);
}
else if (sections[0].equals("GROUP")) {
sentinel.groupIgnores.add(sections[1]);
}
else if(sections[0].equals("PLAYER")) {
sentinel.playerNameIgnores.add(sections[1]);
}
else if(sections[0].equals("ENTITY")) {
SentinelTarget target = SentinelTarget.forName(sections[1]);
if (target != null) {
sentinel.ignores.add(target);
}
}
/*
These target specifiers are not implemented in Sentinel yet and so can't be imported
else if (sections[0].equals("EVENT"))
else if (sections[0].equals("FACTION"))
else if (sections[0].equals("TOWN"))
else if (sections[0].equals("NATION"))
else if (sections[0].equals("WARTEAM"))
else if (sections[0].equals("TEAM"))
else if (sections[0].equals("CLAN"))
*/
}
}
sentinel.fightback = sentry.Retaliate;


// We need to convert the absolutely insane way sentry handled heal rate, into seconds per health
double hpHealedPerPeriod = 1;
if (sentry.HealRate < .5) {
hpHealedPerPeriod = .5 / sentry.HealRate;
}
// The healRate is both used to calculate the hp healed per period, as well as defining
// the period itself.
double secondsPerHpPoint = sentry.HealRate / hpHealedPerPeriod;
// Finally convert to ticks for sentinel and check bounds
sentinel.healRate = (int)Math.ceil(20 * secondsPerHpPoint);
if (sentinel.healRate < SentinelTrait.healRateMin) {
sentinel.healRate = SentinelTrait.healRateMin;
}
else if (sentinel.healRate > SentinelTrait.healRateMax) {
sentinel.healRate = SentinelTrait.healRateMax;
}

double health = sentry.sentryHealth;
if (health < SentinelTrait.healthMin) {
health = SentinelTrait.healthMin;
}
else if (health > SentinelTrait.healthMax) {
health = SentinelTrait.healthMax;
}
sentinel.setHealth(health);
sentinel.setInvincible(sentry.Invincible);
sentinel.needsAmmo = false;
// With sentries, they'll always attack anything they can see
// Projectile range and chaseRange are always equal for them
sentinel.range = sentry.sentryRange;
sentinel.rangedChase = false;
sentinel.respawnTime = sentry.RespawnDelaySeconds * 20;
sentinel.safeShot = false;
sentinel.spawnPoint = sentry.Spawn;

// Sentry uses player name to determine who its guarding, we'll need to
// convert to UUID if we can
if (sentry.guardTarget != null && sentry.guardTarget.length() > 0) {
OfflinePlayer op = Bukkit.getOfflinePlayer(sentry.guardTarget);
if (op != null) {
UUID playerId = op.getUniqueId();
if (playerId != null) {
sentinel.setGuarding(playerId);
}
}
}
}
return convertedCount;
}


}
@@ -3,7 +3,7 @@ authors: ['mcmonkey']
version: ${project.version} (build ${BUILD_NUMBER})
main: org.mcmonkey.sentinel.SentinelPlugin
depend: [Citizens]
softdepend: [Vault]
softdepend: [Vault, Sentry]

commands:
sentinel:
@@ -70,3 +70,5 @@ permissions:
sentinel.info: true
# Edit other people's NPCs
sentinel.admin: true
# Import sentry data
sentinel.sentryimport: true

0 comments on commit 71e8dd0

Please sign in to comment.
You can’t perform that action at this time.