mirror of
https://github.com/CitizensDev/Citizens2.git
synced 2024-11-16 07:35:32 +01:00
Implement new /template generate command, bugfixes
This commit is contained in:
parent
e8eadbfa36
commit
224b43d75b
@ -405,8 +405,10 @@ public class Citizens extends JavaPlugin implements CitizensPlugin {
|
|||||||
traitFactory = new CitizensTraitFactory(this);
|
traitFactory = new CitizensTraitFactory(this);
|
||||||
traitFactory.registerTrait(TraitInfo.create(ShopTrait.class).withSupplier(() -> new ShopTrait(shops)));
|
traitFactory.registerTrait(TraitInfo.create(ShopTrait.class).withSupplier(() -> new ShopTrait(shops)));
|
||||||
selector = new NPCSelector(this);
|
selector = new NPCSelector(this);
|
||||||
templateRegistry = new TemplateRegistry(new File(this.getDataFolder(), "templates").toPath());
|
templateRegistry = new TemplateRegistry(new File(getDataFolder(), "templates").toPath());
|
||||||
|
if (!new File(getDataFolder(), "skins").exists()) {
|
||||||
|
new File(getDataFolder(), "skins").mkdir();
|
||||||
|
}
|
||||||
Bukkit.getPluginManager().registerEvents(new EventListen(), this);
|
Bukkit.getPluginManager().registerEvents(new EventListen(), this);
|
||||||
Bukkit.getPluginManager().registerEvents(new Placeholders(), this);
|
Bukkit.getPluginManager().registerEvents(new Placeholders(), this);
|
||||||
|
|
||||||
|
@ -456,6 +456,7 @@ public class EventListen implements Listener {
|
|||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onNPCKnockback(NPCKnockbackEvent event) {
|
public void onNPCKnockback(NPCKnockbackEvent event) {
|
||||||
|
event.setCancelled(event.getNPC().isProtected());
|
||||||
if (event.getNPC().data().has(NPC.Metadata.KNOCKBACK)) {
|
if (event.getNPC().data().has(NPC.Metadata.KNOCKBACK)) {
|
||||||
event.setCancelled(!event.getNPC().data().get(NPC.Metadata.KNOCKBACK, true));
|
event.setCancelled(!event.getNPC().data().get(NPC.Metadata.KNOCKBACK, true));
|
||||||
}
|
}
|
||||||
|
@ -110,7 +110,7 @@ public class Settings {
|
|||||||
"npc.pathfinding.default-distance-margin", 1),
|
"npc.pathfinding.default-distance-margin", 1),
|
||||||
DEFAULT_HOLOGRAM_RENDERER(
|
DEFAULT_HOLOGRAM_RENDERER(
|
||||||
"The default renderer for holograms, must be one of the following:<br>interaction - matches inbuilt nametags most closely<br>display - allows for different colored backgrounds<br>armorstand - creates an armorstand and teleports it to the player",
|
"The default renderer for holograms, must be one of the following:<br>interaction - matches inbuilt nametags most closely<br>display - allows for different colored backgrounds<br>armorstand - creates an armorstand and teleports it to the player",
|
||||||
"npc.hologram.default-renderer", "interaction"),
|
"npc.hologram.default-renderer", "display"),
|
||||||
DEFAULT_LOOK_CLOSE("Enable look close by default", "npc.default.look-close.enabled", false),
|
DEFAULT_LOOK_CLOSE("Enable look close by default", "npc.default.look-close.enabled", false),
|
||||||
DEFAULT_LOOK_CLOSE_RANGE("Default look close range in blocks", "npc.default.look-close.range", 10),
|
DEFAULT_LOOK_CLOSE_RANGE("Default look close range in blocks", "npc.default.look-close.range", 10),
|
||||||
DEFAULT_NPC_HOLOGRAM_LINE_HEIGHT("Default distance between hologram lines", "npc.hologram.default-line-height",
|
DEFAULT_NPC_HOLOGRAM_LINE_HEIGHT("Default distance between hologram lines", "npc.hologram.default-line-height",
|
||||||
|
@ -23,6 +23,7 @@ import org.bukkit.DyeColor;
|
|||||||
import org.bukkit.GameMode;
|
import org.bukkit.GameMode;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.NamespacedKey;
|
||||||
import org.bukkit.OfflinePlayer;
|
import org.bukkit.OfflinePlayer;
|
||||||
import org.bukkit.Rotation;
|
import org.bukkit.Rotation;
|
||||||
import org.bukkit.Sound;
|
import org.bukkit.Sound;
|
||||||
@ -893,7 +894,9 @@ public class NPCCommands {
|
|||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
for (String part : parts) {
|
for (String part : parts) {
|
||||||
if (part.contains(":")) {
|
if (part.contains(":")) {
|
||||||
Template template = templateRegistry.getTemplateByNamespacedKey(part);
|
int idx = part.indexOf(':');
|
||||||
|
Template template = templateRegistry
|
||||||
|
.getTemplateByKey(new NamespacedKey(part.substring(0, idx), part.substring(idx + 1)));
|
||||||
if (template == null)
|
if (template == null)
|
||||||
continue;
|
continue;
|
||||||
template.apply(npc);
|
template.apply(npc);
|
||||||
@ -3347,7 +3350,8 @@ public class NPCCommands {
|
|||||||
modifiers = { "tpto" },
|
modifiers = { "tpto" },
|
||||||
min = 2,
|
min = 2,
|
||||||
max = 3,
|
max = 3,
|
||||||
permission = "citizens.npc.tpto")
|
permission = "citizens.npc.tpto",
|
||||||
|
parsePlaceholders = true)
|
||||||
@Requirements
|
@Requirements
|
||||||
public void tpto(CommandContext args, CommandSender sender, NPC npc) throws CommandException {
|
public void tpto(CommandContext args, CommandSender sender, NPC npc) throws CommandException {
|
||||||
Entity from = null, to = null;
|
Entity from = null, to = null;
|
||||||
|
@ -3,6 +3,7 @@ package net.citizensnpcs.commands;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.bukkit.NamespacedKey;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
import com.google.common.base.Joiner;
|
import com.google.common.base.Joiner;
|
||||||
@ -36,25 +37,47 @@ public class TemplateCommands {
|
|||||||
min = 2,
|
min = 2,
|
||||||
permission = "citizens.templates.apply")
|
permission = "citizens.templates.apply")
|
||||||
public void apply(CommandContext args, CommandSender sender, NPC npc,
|
public void apply(CommandContext args, CommandSender sender, NPC npc,
|
||||||
@Arg(value = 1, completionsProvider = TemplateCompletions.class) String templateName)
|
@Arg(value = 1, completionsProvider = TemplateCompletions.class) String templateKey)
|
||||||
throws CommandException {
|
throws CommandException {
|
||||||
Template template = null;
|
Template template = null;
|
||||||
if (templateName.contains(":")) {
|
if (templateKey.contains(":")) {
|
||||||
template = registry.getTemplateByNamespacedKey(templateName);
|
int idx = templateKey.indexOf(':');
|
||||||
|
template = registry
|
||||||
|
.getTemplateByKey(new NamespacedKey(templateKey.substring(0, idx), templateKey.substring(idx + 1)));
|
||||||
} else {
|
} else {
|
||||||
Collection<Template> templates = registry.getTemplates(templateName);
|
Collection<Template> templates = registry.getTemplates(templateKey);
|
||||||
if (templates.isEmpty())
|
if (templates.isEmpty())
|
||||||
throw new CommandException(Messages.TEMPLATE_MISSING);
|
throw new CommandException(Messages.TEMPLATE_MISSING);
|
||||||
if (templates.size() > 1)
|
if (templates.size() > 1)
|
||||||
throw new CommandException(Messages.TEMPLATE_PICKER, templateName, Joiner.on(", ").join(templates
|
throw new CommandException(Messages.TEMPLATE_PICKER, templateKey,
|
||||||
.stream().map(t -> t.getNamespace() + ":" + t.getName()).collect(Collectors.toList())));
|
Joiner.on(", ").join(templates.stream().map(t -> t.getKey()).collect(Collectors.toList())));
|
||||||
template = templates.iterator().next();
|
template = templates.iterator().next();
|
||||||
}
|
}
|
||||||
if (template == null)
|
if (template == null)
|
||||||
throw new CommandException(Messages.TEMPLATE_MISSING);
|
throw new CommandException(Messages.TEMPLATE_MISSING);
|
||||||
|
|
||||||
template.apply(npc);
|
template.apply(npc);
|
||||||
Messaging.sendTr(sender, Messages.TEMPLATE_APPLIED, template.getName(), npc.getName());
|
Messaging.sendTr(sender, Messages.TEMPLATE_APPLIED, template.getKey().getKey(), npc.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Command(
|
||||||
|
aliases = { "template", "tpl" },
|
||||||
|
usage = "generate (template namespace:)[name]",
|
||||||
|
desc = "",
|
||||||
|
modifiers = { "generate" },
|
||||||
|
min = 2,
|
||||||
|
max = 2,
|
||||||
|
permission = "citizens.templates.generate")
|
||||||
|
public void generate(CommandContext args, CommandSender sender, NPC npc,
|
||||||
|
@Arg(value = 1, completionsProvider = TemplateCompletions.class) String templateName)
|
||||||
|
throws CommandException {
|
||||||
|
int idx = templateName.indexOf(':');
|
||||||
|
NamespacedKey key = idx == -1 ? new NamespacedKey("generated", templateName)
|
||||||
|
: new NamespacedKey(templateName.substring(0, idx), templateName.substring(idx + 1));
|
||||||
|
if (registry.getTemplateByKey(key) != null)
|
||||||
|
throw new CommandException(Messages.TEMPLATE_CONFLICT);
|
||||||
|
registry.generateTemplateFromNPC(key, npc);
|
||||||
|
Messaging.sendTr(sender, Messages.TEMPLATE_GENERATED, npc.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Command(
|
@Command(
|
||||||
@ -68,7 +91,7 @@ public class TemplateCommands {
|
|||||||
public void list(CommandContext args, CommandSender sender, NPC npc) throws CommandException {
|
public void list(CommandContext args, CommandSender sender, NPC npc) throws CommandException {
|
||||||
Messaging.sendTr(sender, Messages.TEMPLATE_LIST_HEADER);
|
Messaging.sendTr(sender, Messages.TEMPLATE_LIST_HEADER);
|
||||||
for (Template template : registry.getAllTemplates()) {
|
for (Template template : registry.getAllTemplates()) {
|
||||||
Messaging.send(sender, "[[-]] " + template.getNamespace() + ":" + template.getName());
|
Messaging.send(sender, "[[-]] " + template.getKey());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,7 +104,7 @@ public class TemplateCommands {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<String> getCompletions(CommandContext args, CommandSender sender, NPC npc) {
|
public Collection<String> getCompletions(CommandContext args, CommandSender sender, NPC npc) {
|
||||||
return templateRegistry.getAllTemplates().stream().map(t -> t.getNamespace() + ":" + t.getName())
|
return templateRegistry.getAllTemplates().stream().map(t -> t.getKey().toString())
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,8 @@ import net.citizensnpcs.api.util.DataKey;
|
|||||||
import net.citizensnpcs.util.NMS;
|
import net.citizensnpcs.util.NMS;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Persists the current {@link Location} of the {@link NPC}. Will cache last known location if despawned.
|
* Persists the current {@link Location} of the {@link net.citizensnpcs.api.npc.NPC}. Will cache last known location if
|
||||||
|
* despawned.
|
||||||
*/
|
*/
|
||||||
@TraitName("location")
|
@TraitName("location")
|
||||||
public class CurrentLocation extends Trait {
|
public class CurrentLocation extends Trait {
|
||||||
|
@ -28,6 +28,8 @@ import net.citizensnpcs.api.util.SpigotUtil;
|
|||||||
import net.citizensnpcs.util.InventoryMultiplexer;
|
import net.citizensnpcs.util.InventoryMultiplexer;
|
||||||
import net.citizensnpcs.util.NMS;
|
import net.citizensnpcs.util.NMS;
|
||||||
import net.citizensnpcs.util.Util;
|
import net.citizensnpcs.util.Util;
|
||||||
|
import net.kyori.adventure.platform.bukkit.BukkitComponentSerializer;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
|
||||||
public class ItemAction extends NPCShopAction {
|
public class ItemAction extends NPCShopAction {
|
||||||
@Persist
|
@Persist
|
||||||
@ -53,11 +55,11 @@ public class ItemAction extends NPCShopAction {
|
|||||||
@Override
|
@Override
|
||||||
public String describe() {
|
public String describe() {
|
||||||
if (items.size() == 1)
|
if (items.size() == 1)
|
||||||
return items.get(0).getAmount() + " " + Util.prettyEnum(items.get(0).getType());
|
return stringify(items.get(0));
|
||||||
String description = items.size() + " items";
|
String description = items.size() + " items";
|
||||||
for (int i = 0; i < items.size(); i++) {
|
for (int i = 0; i < items.size(); i++) {
|
||||||
ItemStack item = items.get(i);
|
ItemStack item = items.get(i);
|
||||||
description += "\n" + item.getAmount() + " " + Util.prettyEnum(item.getType());
|
description += "\n" + stringify(item);
|
||||||
if (i == 3) {
|
if (i == 3) {
|
||||||
description += "...";
|
description += "...";
|
||||||
break;
|
break;
|
||||||
@ -155,6 +157,7 @@ public class ItemAction extends NPCShopAction {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
private boolean metaMatches(ItemStack needle, ItemStack haystack, List<String> meta) {
|
private boolean metaMatches(ItemStack needle, ItemStack haystack, List<String> meta) {
|
||||||
Map<String, Object> source = NMS.getComponentMap(needle);
|
Map<String, Object> source = NMS.getComponentMap(needle);
|
||||||
Map<String, Object> compare = NMS.getComponentMap(haystack);
|
Map<String, Object> compare = NMS.getComponentMap(haystack);
|
||||||
@ -178,6 +181,14 @@ public class ItemAction extends NPCShopAction {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String stringify(ItemStack item) {
|
||||||
|
if (SUPPORT_TRANSLATABLE) {
|
||||||
|
return BukkitComponentSerializer.legacy().serialize(Component.text(item.getAmount() + " ")
|
||||||
|
.append(Component.translatable().key(item.getTranslationKey())));
|
||||||
|
}
|
||||||
|
return item.getAmount() + " " + Util.prettyEnum(item.getType());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Transaction take(Entity entity, InventoryMultiplexer im, int repeats) {
|
public Transaction take(Entity entity, InventoryMultiplexer im, int repeats) {
|
||||||
if (!(entity instanceof InventoryHolder))
|
if (!(entity instanceof InventoryHolder))
|
||||||
@ -314,4 +325,14 @@ public class ItemAction extends NPCShopAction {
|
|||||||
return action instanceof ItemAction;
|
return action instanceof ItemAction;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean SUPPORT_TRANSLATABLE = true;
|
||||||
|
|
||||||
|
static {
|
||||||
|
try {
|
||||||
|
Class.forName("org.bukkit.Translatable");
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
SUPPORT_TRANSLATABLE = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -414,6 +414,7 @@ public class Messages {
|
|||||||
public static final String TEMPLATE_APPLIED = "citizens.commands.template.applied";
|
public static final String TEMPLATE_APPLIED = "citizens.commands.template.applied";
|
||||||
public static final String TEMPLATE_CONFLICT = "citizens.commands.template.conflict";
|
public static final String TEMPLATE_CONFLICT = "citizens.commands.template.conflict";
|
||||||
public static final String TEMPLATE_DELETED = "citizens.commands.template.delete.deleted";
|
public static final String TEMPLATE_DELETED = "citizens.commands.template.delete.deleted";
|
||||||
|
public static final String TEMPLATE_GENERATED = "citizens.commands.template.generate.generated";
|
||||||
public static final String TEMPLATE_LIST_HEADER = "citizens.commands.template.list.header";
|
public static final String TEMPLATE_LIST_HEADER = "citizens.commands.template.list.header";
|
||||||
public static final String TEMPLATE_MISSING = "citizens.commands.template.missing";
|
public static final String TEMPLATE_MISSING = "citizens.commands.template.missing";
|
||||||
public static final String TEMPLATE_NAMESPACE_EXISTS = "citizens.commands.template.namespace-already-exists";
|
public static final String TEMPLATE_NAMESPACE_EXISTS = "citizens.commands.template.namespace-already-exists";
|
||||||
|
@ -30,7 +30,7 @@ public class MojangSkinGenerator {
|
|||||||
con.setRequestProperty("User-Agent", "Citizens/2.0");
|
con.setRequestProperty("User-Agent", "Citizens/2.0");
|
||||||
con.setRequestProperty("Cache-Control", "no-cache");
|
con.setRequestProperty("Cache-Control", "no-cache");
|
||||||
con.setRequestProperty("Content-Type", "multipart/form-data;boundary=*****");
|
con.setRequestProperty("Content-Type", "multipart/form-data;boundary=*****");
|
||||||
con.setConnectTimeout(1000);
|
con.setConnectTimeout(2000);
|
||||||
con.setReadTimeout(30000);
|
con.setReadTimeout(30000);
|
||||||
out = new DataOutputStream(con.getOutputStream());
|
out = new DataOutputStream(con.getOutputStream());
|
||||||
out.writeBytes("--*****\r\n");
|
out.writeBytes("--*****\r\n");
|
||||||
@ -91,7 +91,7 @@ public class MojangSkinGenerator {
|
|||||||
con.setRequestProperty("Cache-Control", "no-cache");
|
con.setRequestProperty("Cache-Control", "no-cache");
|
||||||
con.setRequestProperty("Accept", "application/json");
|
con.setRequestProperty("Accept", "application/json");
|
||||||
con.setRequestProperty("Content-Type", "application/json");
|
con.setRequestProperty("Content-Type", "application/json");
|
||||||
con.setConnectTimeout(1000);
|
con.setConnectTimeout(2000);
|
||||||
con.setReadTimeout(30000);
|
con.setReadTimeout(30000);
|
||||||
out = new DataOutputStream(con.getOutputStream());
|
out = new DataOutputStream(con.getOutputStream());
|
||||||
JSONObject req = new JSONObject();
|
JSONObject req = new JSONObject();
|
||||||
|
@ -618,6 +618,8 @@
|
|||||||
"citizens.commands.requirements.must-have-selected" : "You must have an NPC selected to execute that command.",
|
"citizens.commands.requirements.must-have-selected" : "You must have an NPC selected to execute that command.",
|
||||||
"citizens.commands.requirements.too-few-arguments" : "Too few arguments.",
|
"citizens.commands.requirements.too-few-arguments" : "Too few arguments.",
|
||||||
"citizens.commands.requirements.too-many-arguments" : "Too many arguments. ",
|
"citizens.commands.requirements.too-many-arguments" : "Too many arguments. ",
|
||||||
|
"citizens.commands.template.generate.generated" : "Generated template from [[{0}]]",
|
||||||
|
"citizens.commands.template.generate.description" : "Generate a template from the selected NPC",
|
||||||
"citizens.commands.template.applied" : "Applied [[{0}]] to [[{1}]].",
|
"citizens.commands.template.applied" : "Applied [[{0}]] to [[{1}]].",
|
||||||
"citizens.commands.template.apply.description" : "Applies a template to the selected NPC",
|
"citizens.commands.template.apply.description" : "Applies a template to the selected NPC",
|
||||||
"citizens.commands.template.apply.help" : "",
|
"citizens.commands.template.apply.help" : "",
|
||||||
|
@ -700,7 +700,8 @@ public class NMSImpl implements NMSBridge {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float getRidingHeightOffset(org.bukkit.entity.Entity entity, org.bukkit.entity.Entity mount) {
|
public float getRidingHeightOffset(org.bukkit.entity.Entity entity, org.bukkit.entity.Entity mount) {
|
||||||
return (float) getHandle(entity).getPassengerRidingPosition(getHandle(mount)).y;
|
Entity handle = getHandle(entity);
|
||||||
|
return (float) (handle.getPassengerRidingPosition(getHandle(mount)).y - handle.position().y);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -911,8 +912,7 @@ public class NMSImpl implements NMSBridge {
|
|||||||
@Override
|
@Override
|
||||||
public void linkTextInteraction(org.bukkit.entity.Player player, org.bukkit.entity.Entity entity,
|
public void linkTextInteraction(org.bukkit.entity.Player player, org.bukkit.entity.Entity entity,
|
||||||
org.bukkit.entity.Entity mount, double offset) {
|
org.bukkit.entity.Entity mount, double offset) {
|
||||||
Interaction handle = (Interaction) getHandle(entity);
|
offset += getRidingHeightOffset(entity, mount);
|
||||||
offset += handle.getPassengerRidingPosition(getHandle(mount)).y;
|
|
||||||
sendPacket(player,
|
sendPacket(player,
|
||||||
new ClientboundBundlePacket(List.of(
|
new ClientboundBundlePacket(List.of(
|
||||||
new ClientboundSetEntityDataPacket(entity.getEntityId(),
|
new ClientboundSetEntityDataPacket(entity.getEntityId(),
|
||||||
|
Loading…
Reference in New Issue
Block a user