Skip to content

Commit

Permalink
Add back a simple /npc script command
Browse files Browse the repository at this point in the history
  • Loading branch information
fullwall committed Jan 23, 2016
1 parent a1c4825 commit 9fcef2c
Show file tree
Hide file tree
Showing 5 changed files with 156 additions and 0 deletions.
30 changes: 30 additions & 0 deletions src/main/java/net/citizensnpcs/commands/NPCCommands.java
@@ -1,6 +1,7 @@
package net.citizensnpcs.commands;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
Expand Down Expand Up @@ -31,6 +32,7 @@
import org.bukkit.entity.Villager.Profession;
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;

import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import com.google.common.collect.Iterables;

Expand Down Expand Up @@ -79,6 +81,7 @@
import net.citizensnpcs.trait.Powered;
import net.citizensnpcs.trait.RabbitType;
import net.citizensnpcs.trait.RabbitType.RabbitTypes;
import net.citizensnpcs.trait.ScriptTrait;
import net.citizensnpcs.trait.SheepTrait;
import net.citizensnpcs.trait.SkinLayers;
import net.citizensnpcs.trait.SkinLayers.Layer;
Expand Down Expand Up @@ -1249,6 +1252,33 @@ public void respawn(CommandContext args, CommandSender sender, NPC npc) {
}
}

@Command(
aliases = { "npc" },
usage = "script --add [files] --remove [files]",
desc = "Controls an NPC's scripts",
modifiers = { "script" },
min = 1,
max = 1,
permission = "citizens.npc.script")
public void script(CommandContext args, CommandSender sender, NPC npc) {
ScriptTrait trait = npc.getTrait(ScriptTrait.class);
if (args.hasValueFlag("add")) {
List<String> files = new ArrayList<String>();
for (String file : args.getFlag("add").split(",")) {
if (!trait.validateFile(file)) {
Messaging.sendErrorTr(sender, Messages.INVALID_SCRIPT_FILE, file);
return;
}
files.add(file);
}
trait.addScripts(files);
}
if (args.hasValueFlag("remove")) {
trait.removeScripts(Arrays.asList(args.getFlag("remove").split(",")));
}
Messaging.sendTr(sender, Messages.CURRENT_SCRIPTS, npc.getName(), Joiner.on("]],[[ ").join(trait.getScripts()));
}

@Command(
aliases = { "npc" },
usage = "select|sel [id|name] (--r range)",
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/net/citizensnpcs/npc/CitizensTraitFactory.java
Expand Up @@ -36,6 +36,7 @@
import net.citizensnpcs.trait.Powered;
import net.citizensnpcs.trait.RabbitType;
import net.citizensnpcs.trait.Saddle;
import net.citizensnpcs.trait.ScriptTrait;
import net.citizensnpcs.trait.SheepTrait;
import net.citizensnpcs.trait.SkinLayers;
import net.citizensnpcs.trait.SlimeSize;
Expand Down Expand Up @@ -68,6 +69,7 @@ public CitizensTraitFactory() {
registerTrait(TraitInfo.create(Powered.class));
registerTrait(TraitInfo.create(RabbitType.class));
registerTrait(TraitInfo.create(Saddle.class));
registerTrait(TraitInfo.create(ScriptTrait.class));
registerTrait(TraitInfo.create(SheepTrait.class));
registerTrait(TraitInfo.create(SkinLayers.class));
registerTrait(TraitInfo.create(NPCSkeletonType.class));
Expand Down
120 changes: 120 additions & 0 deletions src/main/java/net/citizensnpcs/trait/ScriptTrait.java
@@ -0,0 +1,120 @@
package net.citizensnpcs.trait;

import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.bukkit.Bukkit;
import org.bukkit.plugin.java.JavaPlugin;

import net.citizensnpcs.Citizens;
import net.citizensnpcs.api.CitizensAPI;
import net.citizensnpcs.api.persistence.Persist;
import net.citizensnpcs.api.scripting.CompileCallback;
import net.citizensnpcs.api.scripting.Script;
import net.citizensnpcs.api.scripting.ScriptFactory;
import net.citizensnpcs.api.trait.Trait;
import net.citizensnpcs.api.trait.TraitName;
import net.citizensnpcs.api.util.DataKey;

@TraitName("scripttrait")
public class ScriptTrait extends Trait {
@Persist
public List<String> files = new ArrayList<String>();
private final List<RunnableScript> runnableScripts = new ArrayList<RunnableScript>();

public ScriptTrait() {
super("scripttrait");
}

public void addScripts(List<String> scripts) {
for (String f : scripts) {
if (!files.contains(f) && validateFile(f)) {
loadScript(f);
files.add(f);
}
}
}

public List<String> getScripts() {
return files;
}

@Override
public void load(DataKey key) {
for (String file : files) {
if (validateFile(file)) {
loadScript(file);
}
}
}

public void loadScript(final String file) {
File f = new File(JavaPlugin.getPlugin(Citizens.class).getScriptFolder(), file);
CitizensAPI.getScriptCompiler().compile(f).cache(true).withCallback(new CompileCallback() {
@Override
public void onScriptCompiled(String sourceDescriptor, ScriptFactory compiled) {
System.out.println("compiled");
final Script newInstance = compiled.newInstance();
Bukkit.getScheduler().scheduleSyncDelayedTask(CitizensAPI.getPlugin(), new Runnable() {
@Override
public void run() {
try {
newInstance.invoke("onLoad", npc);
} catch (RuntimeException e) {
if (!(e.getCause() instanceof NoSuchMethodException)) {
throw e;
}
}
runnableScripts.add(new RunnableScript(newInstance, file));
}
});
}
}).beginWithFuture();
}

public void removeScripts(List<String> scripts) {
files.removeAll(scripts);
Iterator<RunnableScript> itr = runnableScripts.iterator();
while (itr.hasNext()) {
if (scripts.remove(itr.next().file)) {
itr.remove();
}
}
}

@Override
public void run() {
Iterator<RunnableScript> itr = runnableScripts.iterator();
while (itr.hasNext()) {
try {
itr.next().script.invoke("run", npc);
} catch (RuntimeException e) {
if (e.getCause() instanceof NoSuchMethodException) {
itr.remove();
} else {
throw e;
}
}
}
}

public boolean validateFile(String file) {
File f = new File(JavaPlugin.getPlugin(Citizens.class).getScriptFolder(), file);
if (!f.exists() || !f.getParentFile().equals(JavaPlugin.getPlugin(Citizens.class).getScriptFolder())) {
return false;
}
return CitizensAPI.getScriptCompiler().canCompile(f);
}

private static class RunnableScript {
String file;
Script script;

public RunnableScript(Script script, String file) {
this.script = script;
this.file = file;
}
}
}
2 changes: 2 additions & 0 deletions src/main/java/net/citizensnpcs/util/Messages.java
Expand Up @@ -49,6 +49,7 @@ public class Messages {
public static final String CONTROLLABLE_SET = "citizens.commands.npc.controllable.set";
public static final String COPIER_EDITOR_BEGIN = "citizens.editors.copier.begin";
public static final String COPIER_EDITOR_END = "citizens.editors.copier.end";
public static final String CURRENT_SCRIPTS = "citizens.commands.npc.script.current-scripts";
public static final String CURRENT_WAYPOINT_PROVIDER = "citizens.waypoints.current-provider";
public static final String DATABASE_CONNECTION_FAILED = "citizens.notifications.database-connection-failed";
public static final String DELAY_TRIGGER_PROMPT = "citizens.editors.waypoints.triggers.delay.prompt";
Expand Down Expand Up @@ -104,6 +105,7 @@ public class Messages {
public static final String INVALID_POSE_NAME = "citizens.commands.npc.pose.invalid-name";
public static final String INVALID_PROFESSION = "citizens.commands.npc.profession.invalid-profession";
public static final String INVALID_RABBIT_TYPE = "citizens.commands.npc.rabbittype.invalid-type";
public static final String INVALID_SCRIPT_FILE = "citizens.commands.npc.script.invalid-file";
public static final String INVALID_SHEEP_COLOR = "citizens.commands.npc.sheep.invalid-color";
public static final String INVALID_SKELETON_TYPE = "citizens.commands.npc.skeletontype.invalid-type";
public static final String INVALID_SOUND = "citizens.commands.npc.sound.invalid-sound";
Expand Down
2 changes: 2 additions & 0 deletions src/main/resources/messages_en.properties
Expand Up @@ -97,6 +97,8 @@ citizens.commands.npc.rename.renamed=You renamed [[{0}]] to [[{1}]].
citizens.commands.npc.respawn.delay-set=Respawn delay set to [[{0}]].
citizens.commands.npc.respawn.describe=Respawn delay is currently [[{0}]].
citizens.commands.npc.select.already-selected=You already have that NPC selected.
citizens.commands.npc.script.invalid-file=Unknown or unavailable script ''[[{0}]]''.
citizens.commands.npc.script.current-scripts=[[{0}]]''s current scripts are [[{1}]].
citizens.commands.npc.skin.set=[[{0}]]''s skin name set to [[{1}]].
citizens.commands.npc.skin.cleared=[[{0}]]''s skin name was cleared.
citizens.commands.npc.skin.layers-set=[[{0}]]''s skin layers: cape - [[{1}]], hat - [[{2}]], jacket - [[{3}]], sleeves - [[{4}]], pants - [[{5}]].
Expand Down

0 comments on commit 9fcef2c

Please sign in to comment.