Compare commits

...

8 Commits

Author SHA1 Message Date
D3v1s0m
f170fc28ad added camel_sitting property
Some checks failed
continuous-integration/drone/push Build is failing
2024-06-24 23:30:33 +02:00
D3v1s0m
4db56a2b20 fix action commands, ughh 2024-06-24 23:30:23 +02:00
D3v1s0m
4fb964fa60 add config option fake-enforce-secure-chat to disable secure chat popup 2024-06-24 23:30:23 +02:00
D3v1s0m
bca00f98cb update dependencies 2024-06-24 23:30:23 +02:00
D3v1s0m
1bd35d6dc2 partial fix for help message 2024-06-24 23:30:23 +02:00
D3v1s0m
c731a35dd3 small action command(s) fix 2024-06-24 23:30:23 +02:00
D3v1s0m
91e737bc22 %blank% for empty hologram line 2024-06-24 23:30:23 +02:00
D3v1s0m
b1cea2a860 expose action registry to api and added action factory 2024-06-24 23:30:23 +02:00
38 changed files with 258 additions and 78 deletions

@ -1,6 +1,8 @@
package lol.pyr.znpcsplus.api;
import lol.pyr.znpcsplus.api.entity.EntityPropertyRegistry;
import lol.pyr.znpcsplus.api.interaction.ActionFactory;
import lol.pyr.znpcsplus.api.interaction.ActionRegistry;
import lol.pyr.znpcsplus.api.npc.NpcRegistry;
import lol.pyr.znpcsplus.api.npc.NpcTypeRegistry;
import lol.pyr.znpcsplus.api.skin.SkinDescriptorFactory;
@ -27,6 +29,18 @@ public interface NpcApi {
*/
EntityPropertyRegistry getPropertyRegistry();
/**
* Gets the action registry.
* @return the action registry
*/
ActionRegistry getActionRegistry();
/**
* Gets the action factory.
* @return the action factory
*/
ActionFactory getActionFactory();
/**
* Gets the skin descriptor factory.
* @return the skin descriptor factory

@ -48,6 +48,7 @@ public interface PropertyHolder {
* when using item properties, read https://github.com/Pyrbu/ZNPCsPlus/pull/129#issuecomment-1948777764
*
* @param key Unique key representing a property
* @return the {@link ItemStack} associated with the provided property key and this holder
*/
ItemStack getItemProperty(EntityProperty<?> key);

@ -0,0 +1,10 @@
package lol.pyr.znpcsplus.api.interaction;
@SuppressWarnings("unused")
public interface ActionFactory {
InteractionAction createConsoleCommandAction(String command, InteractionType interactionType, long cooldown, long delay);
InteractionAction createMessageAction(String message, InteractionType interactionType, long cooldown, long delay);
InteractionAction createPlayerChatAction(String message, InteractionType interactionType, long cooldown, long delay);
InteractionAction createPlayerCommandAction(String command, InteractionType interactionType, long cooldown, long delay);
InteractionAction createSwitchServerAction(String server, InteractionType interactionType, long cooldown, long delay);
}

@ -0,0 +1,7 @@
package lol.pyr.znpcsplus.api.interaction;
public interface ActionRegistry {
void register(InteractionActionType<?> type);
void unregister(Class<? extends InteractionAction> clazz);
}

@ -1,4 +1,4 @@
package lol.pyr.znpcsplus.interaction;
package lol.pyr.znpcsplus.api.interaction;
public interface InteractionActionType<T> {
String serialize(T obj);

@ -75,6 +75,31 @@ public interface Npc extends PropertyHolder {
*/
List<? extends InteractionAction> getActions();
/**
* Removes an action from this NPC
* @param index The index of the action to remove
*/
void removeAction(int index);
/**
* Adds an action to this NPC
* @param action The {@link InteractionAction} to add
*/
void addAction(InteractionAction action);
/**
* Edits an action for this NPC
* @param index The index of the action to edit
* @param action The {@link InteractionAction} to set
*/
void editAction(int index, InteractionAction action);
/**
* Clears all actions from this NPC
*/
void clearActions();
/**
* Gets if this NPC is visible to a player
* @param player The {@link Player} to check

@ -31,17 +31,17 @@ publishing {
}
dependencies {
compileOnly "me.clip:placeholderapi:2.11.5" // Placeholder support
compileOnly "me.clip:placeholderapi:2.11.6" // Placeholder support
implementation "com.google.code.gson:gson:2.10.1" // JSON parsing
implementation "org.bstats:bstats-bukkit:3.0.2" // Plugin stats
implementation "me.robertlit:SpigotResourcesAPI:2.0" // Spigot API wrapper for update checker
implementation "com.github.retrooper.packetevents:spigot:2.3.0" // Packets
implementation "space.arim.dazzleconf:dazzleconf-ext-snakeyaml:1.2.1" // Configs
implementation "lol.pyr:director-adventure:2.1.1" // Commands
implementation "lol.pyr:director-adventure:2.1.2" // Commands
// Fancy text library
implementation "net.kyori:adventure-platform-bukkit:4.3.2"
implementation "net.kyori:adventure-text-minimessage:4.15.0"
implementation "net.kyori:adventure-platform-bukkit:4.3.3"
implementation "net.kyori:adventure-text-minimessage:4.17.0"
implementation project(":api")
}

@ -27,7 +27,8 @@ import lol.pyr.znpcsplus.config.ConfigManager;
import lol.pyr.znpcsplus.conversion.DataImporterRegistry;
import lol.pyr.znpcsplus.entity.EntityPropertyImpl;
import lol.pyr.znpcsplus.entity.EntityPropertyRegistryImpl;
import lol.pyr.znpcsplus.interaction.ActionRegistry;
import lol.pyr.znpcsplus.interaction.ActionFactoryImpl;
import lol.pyr.znpcsplus.interaction.ActionRegistryImpl;
import lol.pyr.znpcsplus.interaction.InteractionPacketListener;
import lol.pyr.znpcsplus.npc.*;
import lol.pyr.znpcsplus.packets.*;
@ -42,6 +43,7 @@ import lol.pyr.znpcsplus.tasks.NpcProcessorTask;
import lol.pyr.znpcsplus.tasks.ViewableHideOnLeaveListener;
import lol.pyr.znpcsplus.updater.UpdateChecker;
import lol.pyr.znpcsplus.updater.UpdateNotificationListener;
import lol.pyr.znpcsplus.user.ClientPacketListener;
import lol.pyr.znpcsplus.user.UserListener;
import lol.pyr.znpcsplus.user.UserManager;
import lol.pyr.znpcsplus.util.*;
@ -117,7 +119,9 @@ public class ZNpcsPlus {
PacketFactory packetFactory = setupPacketFactory(scheduler, propertyRegistry, configManager);
propertyRegistry.registerTypes(bootstrap, packetFactory, textSerializer);
ActionRegistry actionRegistry = new ActionRegistry();
BungeeConnector bungeeConnector = new BungeeConnector(bootstrap);
ActionRegistryImpl actionRegistry = new ActionRegistryImpl();
ActionFactoryImpl actionFactory = new ActionFactoryImpl(scheduler, adventure, textSerializer, bungeeConnector);
NpcTypeRegistryImpl typeRegistry = new NpcTypeRegistryImpl();
NpcRegistryImpl npcRegistry = new NpcRegistryImpl(configManager, this, packetFactory, actionRegistry,
scheduler, typeRegistry, propertyRegistry, textSerializer);
@ -126,7 +130,6 @@ public class ZNpcsPlus {
UserManager userManager = new UserManager();
shutdownTasks.add(userManager::shutdown);
BungeeConnector bungeeConnector = new BungeeConnector(bootstrap);
DataImporterRegistry importerRegistry = new DataImporterRegistry(configManager, adventure,
scheduler, packetFactory, textSerializer, typeRegistry, getDataFolder().getParentFile(),
propertyRegistry, skinCache, npcRegistry, bungeeConnector);
@ -139,6 +142,7 @@ public class ZNpcsPlus {
typeRegistry.registerDefault(packetEvents, propertyRegistry);
actionRegistry.registerTypes(scheduler, adventure, textSerializer, bungeeConnector);
packetEvents.getEventManager().registerListener(new InteractionPacketListener(userManager, npcRegistry, typeRegistry, scheduler), PacketListenerPriority.MONITOR);
packetEvents.getEventManager().registerListener(new ClientPacketListener(configManager), PacketListenerPriority.LOWEST);
new Metrics(bootstrap, 18244);
pluginManager.registerEvents(new UserListener(userManager), bootstrap);
@ -177,7 +181,7 @@ public class ZNpcsPlus {
}
}
NpcApiProvider.register(bootstrap, new ZNpcsPlusApi(npcRegistry, typeRegistry, propertyRegistry, skinCache));
NpcApiProvider.register(bootstrap, new ZNpcsPlusApi(npcRegistry, typeRegistry, propertyRegistry, actionRegistry, actionFactory, skinCache));
log(ChatColor.WHITE + " * Loading complete! (" + (System.currentTimeMillis() - before) + "ms)");
log("");
@ -227,7 +231,7 @@ public class ZNpcsPlus {
}
private void registerCommands(NpcRegistryImpl npcRegistry, MojangSkinCache skinCache, BukkitAudiences adventure,
ActionRegistry actionRegistry, NpcTypeRegistryImpl typeRegistry,
ActionRegistryImpl actionRegistry, NpcTypeRegistryImpl typeRegistry,
EntityPropertyRegistryImpl propertyRegistry, DataImporterRegistry importerRegistry,
ConfigManager configManager) {

@ -2,10 +2,14 @@ package lol.pyr.znpcsplus;
import lol.pyr.znpcsplus.api.NpcApi;
import lol.pyr.znpcsplus.api.entity.EntityPropertyRegistry;
import lol.pyr.znpcsplus.api.interaction.ActionFactory;
import lol.pyr.znpcsplus.api.interaction.ActionRegistry;
import lol.pyr.znpcsplus.api.npc.NpcRegistry;
import lol.pyr.znpcsplus.api.npc.NpcTypeRegistry;
import lol.pyr.znpcsplus.api.skin.SkinDescriptorFactory;
import lol.pyr.znpcsplus.entity.EntityPropertyRegistryImpl;
import lol.pyr.znpcsplus.interaction.ActionFactoryImpl;
import lol.pyr.znpcsplus.interaction.ActionRegistryImpl;
import lol.pyr.znpcsplus.npc.NpcRegistryImpl;
import lol.pyr.znpcsplus.npc.NpcTypeRegistryImpl;
import lol.pyr.znpcsplus.skin.SkinDescriptorFactoryImpl;
@ -15,12 +19,16 @@ public class ZNpcsPlusApi implements NpcApi {
private final NpcRegistryImpl npcRegistry;
private final NpcTypeRegistryImpl typeRegistry;
private final EntityPropertyRegistryImpl propertyRegistry;
private final ActionRegistryImpl actionRegistry;
private final ActionFactoryImpl actionFactory;
private final SkinDescriptorFactoryImpl skinDescriptorFactory;
public ZNpcsPlusApi(NpcRegistryImpl npcRegistry, NpcTypeRegistryImpl typeRegistry, EntityPropertyRegistryImpl propertyRegistry, MojangSkinCache skinCache) {
public ZNpcsPlusApi(NpcRegistryImpl npcRegistry, NpcTypeRegistryImpl typeRegistry, EntityPropertyRegistryImpl propertyRegistry, ActionRegistryImpl actionRegistry, ActionFactoryImpl actionFactory, MojangSkinCache skinCache) {
this.npcRegistry = npcRegistry;
this.typeRegistry = typeRegistry;
this.propertyRegistry = propertyRegistry;
this.actionRegistry = actionRegistry;
this.actionFactory = actionFactory;
this.skinDescriptorFactory = new SkinDescriptorFactoryImpl(skinCache);
}
@ -39,6 +47,17 @@ public class ZNpcsPlusApi implements NpcApi {
return propertyRegistry;
}
@Override
public ActionRegistry getActionRegistry() {
return actionRegistry;
}
@Override
public ActionFactory getActionFactory() {
return actionFactory;
}
@Override
public SkinDescriptorFactory getSkinDescriptorFactory() {
return skinDescriptorFactory;

@ -3,7 +3,7 @@ package lol.pyr.znpcsplus.commands.action;
import lol.pyr.director.adventure.command.CommandContext;
import lol.pyr.director.adventure.command.CommandHandler;
import lol.pyr.director.common.command.CommandExecutionException;
import lol.pyr.znpcsplus.interaction.ActionRegistry;
import lol.pyr.znpcsplus.interaction.ActionRegistryImpl;
import lol.pyr.znpcsplus.interaction.InteractionCommandHandler;
import lol.pyr.znpcsplus.npc.NpcRegistryImpl;
import net.kyori.adventure.text.Component;
@ -15,9 +15,9 @@ import java.util.stream.Collectors;
public class ActionAddCommand implements CommandHandler {
private final NpcRegistryImpl npcRegistry;
private final ActionRegistry actionRegistry;
private final ActionRegistryImpl actionRegistry;
public ActionAddCommand(NpcRegistryImpl npcRegistry, ActionRegistry actionRegistry) {
public ActionAddCommand(NpcRegistryImpl npcRegistry, ActionRegistryImpl actionRegistry) {
this.npcRegistry = npcRegistry;
this.actionRegistry = actionRegistry;
}

@ -3,8 +3,8 @@ package lol.pyr.znpcsplus.commands.action;
import lol.pyr.director.adventure.command.CommandContext;
import lol.pyr.director.adventure.command.CommandHandler;
import lol.pyr.director.common.command.CommandExecutionException;
import lol.pyr.znpcsplus.interaction.ActionRegistry;
import lol.pyr.znpcsplus.interaction.InteractionActionImpl;
import lol.pyr.znpcsplus.api.interaction.InteractionAction;
import lol.pyr.znpcsplus.interaction.ActionRegistryImpl;
import lol.pyr.znpcsplus.interaction.InteractionCommandHandler;
import lol.pyr.znpcsplus.npc.NpcEntryImpl;
import lol.pyr.znpcsplus.npc.NpcRegistryImpl;
@ -18,11 +18,11 @@ import java.util.stream.Stream;
public class ActionEditCommand implements CommandHandler {
private final NpcRegistryImpl npcRegistry;
private final ActionRegistry actionRegistry;
private final ActionRegistryImpl actionRegistry;
private InteractionCommandHandler commandHandler = null;
public ActionEditCommand(NpcRegistryImpl npcRegistry, ActionRegistry actionRegistry) {
public ActionEditCommand(NpcRegistryImpl npcRegistry, ActionRegistryImpl actionRegistry) {
this.npcRegistry = npcRegistry;
this.actionRegistry = actionRegistry;
}
@ -42,7 +42,7 @@ public class ActionEditCommand implements CommandHandler {
context.send(Component.text("Invalid action type, available action types:\n" +
commands.stream().map(InteractionCommandHandler::getSubcommandName).collect(Collectors.joining(", ")), NamedTextColor.RED));
}
InteractionActionImpl newAction = this.commandHandler.parse(context);
InteractionAction newAction = this.commandHandler.parse(context);
entry.getNpc().editAction(index, newAction);
context.send(Component.text("Edited action with index " + index + " of Npc " + entry.getId(), NamedTextColor.GREEN));
}

@ -3,6 +3,7 @@ package lol.pyr.znpcsplus.commands.action;
import lol.pyr.director.adventure.command.CommandContext;
import lol.pyr.director.adventure.command.CommandHandler;
import lol.pyr.director.common.command.CommandExecutionException;
import lol.pyr.znpcsplus.api.interaction.InteractionAction;
import lol.pyr.znpcsplus.interaction.InteractionActionImpl;
import lol.pyr.znpcsplus.npc.NpcEntryImpl;
import lol.pyr.znpcsplus.npc.NpcRegistryImpl;
@ -21,10 +22,12 @@ public class ActionListCommand implements CommandHandler {
public void run(CommandContext context) throws CommandExecutionException {
context.setUsage(context.getLabel() + " action list <id>");
NpcEntryImpl entry = context.parse(NpcEntryImpl.class);
List<InteractionActionImpl> actions = entry.getNpc().getActions();
List<InteractionAction> actions = entry.getNpc().getActions();
context.send("Actions of Npc " + entry.getId() + ":");
for (int i = 0; i < actions.size(); i++) {
context.send(actions.get(i).getInfo(entry.getId(), i, context));
if (actions.get(i) instanceof InteractionActionImpl) {
context.send(((InteractionActionImpl) actions.get(i)).getInfo(entry.getId(), i, context));
}
}
}

@ -73,4 +73,9 @@ public interface MainConfig {
@ConfComments("The display name to use for npcs in the player list (aka tab)")
@DefaultString("ZNPC[{id}]")
String tabDisplayName();
@ConfKey("fake-enforce-secure-chat")
@ConfComments("Should the plugin fake the enforce secure chat packet to hide the popup?")
@DefaultBoolean(false)
boolean fakeEnforceSecureChat();
}

@ -1,8 +1,8 @@
package lol.pyr.znpcsplus.conversion.citizens.model.traits;
import lol.pyr.znpcsplus.api.interaction.InteractionAction;
import lol.pyr.znpcsplus.api.interaction.InteractionType;
import lol.pyr.znpcsplus.conversion.citizens.model.SectionCitizensTrait;
import lol.pyr.znpcsplus.interaction.InteractionActionImpl;
import lol.pyr.znpcsplus.interaction.consolecommand.ConsoleCommandAction;
import lol.pyr.znpcsplus.interaction.playercommand.PlayerCommandAction;
import lol.pyr.znpcsplus.npc.NpcImpl;
@ -35,7 +35,7 @@ public class CommandTrait extends SectionCitizensTrait {
int cooldown = commandSection.getInt("cooldown", 0);
int delay = commandSection.getInt("delay", 0);
if (command != null) {
InteractionActionImpl action;
InteractionAction action;
if (isPlayerCommand) {
action = new PlayerCommandAction(scheduler, command, clickType, cooldown, delay);
} else {

@ -143,7 +143,7 @@ public class FancyNpcsImporter implements DataImporter {
if (!messages.isEmpty()) {
long cooldown = npcSection.getLong("interactionCooldown", 0);
for (String message : messages) {
npc.addAction(new MessageAction(adventure, message, InteractionType.ANY_CLICK, textSerializer, cooldown, 0));
npc.addAction(new MessageAction(adventure, textSerializer, message, InteractionType.ANY_CLICK, cooldown, 0));
}
}
String id = npcSection.getString("name");

@ -4,6 +4,7 @@ import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import lol.pyr.znpcsplus.api.interaction.InteractionAction;
import lol.pyr.znpcsplus.api.interaction.InteractionType;
import lol.pyr.znpcsplus.api.skin.SkinDescriptor;
import lol.pyr.znpcsplus.config.ConfigManager;
@ -12,7 +13,6 @@ import lol.pyr.znpcsplus.conversion.znpcs.model.*;
import lol.pyr.znpcsplus.entity.EntityPropertyImpl;
import lol.pyr.znpcsplus.entity.EntityPropertyRegistryImpl;
import lol.pyr.znpcsplus.hologram.HologramImpl;
import lol.pyr.znpcsplus.interaction.InteractionActionImpl;
import lol.pyr.znpcsplus.interaction.consolecommand.ConsoleCommandAction;
import lol.pyr.znpcsplus.interaction.message.MessageAction;
import lol.pyr.znpcsplus.interaction.playerchat.PlayerChatAction;
@ -146,7 +146,7 @@ public class ZNpcImporter implements DataImporter {
for (String line : lines) {
// Create a new message action for each line of text
InteractionActionImpl action = new MessageAction(adventure, line, InteractionType.ANY_CLICK, textSerializer, 0, totalDelay);
InteractionAction action = new MessageAction(adventure, textSerializer, line, InteractionType.ANY_CLICK, 0, totalDelay);
npc.addAction(action);
}
}
@ -222,7 +222,7 @@ public class ZNpcImporter implements DataImporter {
throw new IllegalArgumentException("Couldn't adapt znpcs click type: " + clickType);
}
private InteractionActionImpl adaptAction(String type, InteractionType clickType, String parameter, int cooldown) {
private InteractionAction adaptAction(String type, InteractionType clickType, String parameter, int cooldown) {
switch (type.toLowerCase()) {
case "cmd":
return new PlayerCommandAction(taskScheduler, parameter, clickType, cooldown * 1000L, 0);
@ -231,9 +231,9 @@ public class ZNpcImporter implements DataImporter {
case "chat":
return new PlayerChatAction(taskScheduler, parameter, clickType, cooldown * 1000L, 0);
case "message":
return new MessageAction(adventure, parameter, clickType, textSerializer, cooldown * 1000L, 0);
return new MessageAction(adventure, textSerializer, parameter, clickType, cooldown * 1000L, 0);
case "server":
return new SwitchServerAction(parameter, clickType, cooldown * 1000L, 0, bungeeConnector);
return new SwitchServerAction(bungeeConnector, parameter, clickType, cooldown * 1000L, 0);
}
throw new IllegalArgumentException("Couldn't adapt znpcs click action: " + type);
}

@ -6,15 +6,25 @@ import lol.pyr.znpcsplus.entity.EntityPropertyRegistryImpl;
import lol.pyr.znpcsplus.packets.PacketFactory;
import lol.pyr.znpcsplus.util.NpcLocation;
import net.kyori.adventure.text.Component;
import org.bukkit.entity.Player;
public class HologramText extends HologramLine<Component> {
private static final Component BLANK = Component.text("%blank%");
public HologramText(EntityPropertyRegistryImpl propertyRegistry, PacketFactory packetFactory, NpcLocation location, Component text) {
super(text, packetFactory, EntityTypes.ARMOR_STAND, location);
addProperty(propertyRegistry.getByName("name"));
addProperty(propertyRegistry.getByName("invisible"));
}
@Override
public void show(Player player) {
if (!getValue().equals(BLANK)) {
super.show(player);
}
}
@SuppressWarnings("unchecked")
@Override
public <T> T getProperty(EntityProperty<T> key) {

@ -0,0 +1,48 @@
package lol.pyr.znpcsplus.interaction;
import lol.pyr.znpcsplus.api.interaction.ActionFactory;
import lol.pyr.znpcsplus.api.interaction.InteractionAction;
import lol.pyr.znpcsplus.api.interaction.InteractionType;
import lol.pyr.znpcsplus.interaction.consolecommand.ConsoleCommandAction;
import lol.pyr.znpcsplus.interaction.message.MessageAction;
import lol.pyr.znpcsplus.interaction.playerchat.PlayerChatAction;
import lol.pyr.znpcsplus.interaction.playercommand.PlayerCommandAction;
import lol.pyr.znpcsplus.interaction.switchserver.SwitchServerAction;
import lol.pyr.znpcsplus.scheduling.TaskScheduler;
import lol.pyr.znpcsplus.util.BungeeConnector;
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
public class ActionFactoryImpl implements ActionFactory {
private final TaskScheduler scheduler;
private final BukkitAudiences adventure;
private final LegacyComponentSerializer textSerializer;
private final BungeeConnector bungeeConnector;
public ActionFactoryImpl(TaskScheduler scheduler, BukkitAudiences adventure, LegacyComponentSerializer textSerializer, BungeeConnector bungeeConnector) {
this.scheduler = scheduler;
this.adventure = adventure;
this.textSerializer = textSerializer;
this.bungeeConnector = bungeeConnector;
}
public InteractionAction createConsoleCommandAction(String command, InteractionType interactionType, long cooldown, long delay) {
return new ConsoleCommandAction(this.scheduler, command, interactionType, cooldown, delay);
}
public InteractionAction createMessageAction(String message, InteractionType interactionType, long cooldown, long delay) {
return new MessageAction(this.adventure, textSerializer, message, interactionType, cooldown, delay);
}
public InteractionAction createPlayerChatAction(String message, InteractionType interactionType, long cooldown, long delay) {
return new PlayerChatAction(this.scheduler, message, interactionType, cooldown, delay);
}
public InteractionAction createPlayerCommandAction(String command, InteractionType interactionType, long cooldown, long delay) {
return new PlayerCommandAction(this.scheduler, command, interactionType, cooldown, delay);
}
public InteractionAction createSwitchServerAction(String server, InteractionType interactionType, long cooldown, long delay) {
return new SwitchServerAction(bungeeConnector, server, interactionType, cooldown, delay);
}
}

@ -1,6 +1,6 @@
package lol.pyr.znpcsplus.interaction;
import lol.pyr.znpcsplus.api.interaction.InteractionAction;
import lol.pyr.znpcsplus.api.interaction.*;
import lol.pyr.znpcsplus.interaction.consolecommand.ConsoleCommandActionType;
import lol.pyr.znpcsplus.interaction.message.MessageActionType;
import lol.pyr.znpcsplus.interaction.playerchat.PlayerChatActionType;
@ -17,12 +17,9 @@ import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class ActionRegistry {
public class ActionRegistryImpl implements ActionRegistry {
private final Map<Class<?>, InteractionActionType<?>> serializerMap = new HashMap<>();
public ActionRegistry() {
}
public void registerTypes(TaskScheduler taskScheduler, BukkitAudiences adventure, LegacyComponentSerializer textSerializer, BungeeConnector bungeeConnector) {
register(new ConsoleCommandActionType(taskScheduler));
register(new PlayerCommandActionType(taskScheduler));

@ -3,6 +3,7 @@ package lol.pyr.znpcsplus.interaction;
import lol.pyr.director.adventure.command.CommandContext;
import lol.pyr.director.adventure.command.CommandHandler;
import lol.pyr.director.common.command.CommandExecutionException;
import lol.pyr.znpcsplus.api.interaction.InteractionAction;
import lol.pyr.znpcsplus.npc.NpcEntryImpl;
import lol.pyr.znpcsplus.npc.NpcImpl;
import net.kyori.adventure.text.Component;
@ -11,7 +12,7 @@ import net.kyori.adventure.text.format.NamedTextColor;
public interface InteractionCommandHandler extends CommandHandler {
String getSubcommandName();
InteractionActionImpl parse(CommandContext context) throws CommandExecutionException;
InteractionAction parse(CommandContext context) throws CommandExecutionException;
void appendUsage(CommandContext context);
@Override

@ -4,7 +4,7 @@ import lol.pyr.director.adventure.command.CommandContext;
import lol.pyr.director.common.command.CommandExecutionException;
import lol.pyr.znpcsplus.api.interaction.InteractionType;
import lol.pyr.znpcsplus.interaction.InteractionActionImpl;
import lol.pyr.znpcsplus.interaction.InteractionActionType;
import lol.pyr.znpcsplus.api.interaction.InteractionActionType;
import lol.pyr.znpcsplus.interaction.InteractionCommandHandler;
import lol.pyr.znpcsplus.scheduling.TaskScheduler;

@ -17,7 +17,7 @@ public class MessageAction extends InteractionActionImpl {
private final String message;
private final LegacyComponentSerializer textSerializer;
public MessageAction(BukkitAudiences adventure, String message, InteractionType interactionType, LegacyComponentSerializer textSerializer, long cooldown, long delay) {
public MessageAction(BukkitAudiences adventure, LegacyComponentSerializer textSerializer, String message, InteractionType interactionType, long cooldown, long delay) {
super(cooldown, delay, interactionType);
this.adventure = adventure;
this.message = message;

@ -4,7 +4,7 @@ import lol.pyr.director.adventure.command.CommandContext;
import lol.pyr.director.common.command.CommandExecutionException;
import lol.pyr.znpcsplus.api.interaction.InteractionType;
import lol.pyr.znpcsplus.interaction.InteractionActionImpl;
import lol.pyr.znpcsplus.interaction.InteractionActionType;
import lol.pyr.znpcsplus.api.interaction.InteractionActionType;
import lol.pyr.znpcsplus.interaction.InteractionCommandHandler;
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
@ -32,7 +32,7 @@ public class MessageActionType implements InteractionActionType<MessageAction>,
public MessageAction deserialize(String str) {
String[] split = str.split(";");
InteractionType type = split.length > 2 ? InteractionType.valueOf(split[2]) : InteractionType.ANY_CLICK;
return new MessageAction(adventure, new String(Base64.getDecoder().decode(split[0]), StandardCharsets.UTF_8), type, textSerializer, Long.parseLong(split[1]), Long.parseLong(split.length > 3 ? split[3] : "0"));
return new MessageAction(adventure, textSerializer, new String(Base64.getDecoder().decode(split[0]), StandardCharsets.UTF_8), type, Long.parseLong(split[1]), Long.parseLong(split.length > 3 ? split[3] : "0"));
}
@Override
@ -56,7 +56,7 @@ public class MessageActionType implements InteractionActionType<MessageAction>,
long cooldown = (long) (context.parse(Double.class) * 1000D);
long delay = (long) (context.parse(Integer.class) * 1D);
String message = context.dumpAllArgs();
return new MessageAction(adventure, message, type, textSerializer, cooldown, delay);
return new MessageAction(adventure, textSerializer, message, type, cooldown, delay);
}
@Override

@ -2,9 +2,9 @@ package lol.pyr.znpcsplus.interaction.playerchat;
import lol.pyr.director.adventure.command.CommandContext;
import lol.pyr.director.common.command.CommandExecutionException;
import lol.pyr.znpcsplus.api.interaction.InteractionAction;
import lol.pyr.znpcsplus.api.interaction.InteractionActionType;
import lol.pyr.znpcsplus.api.interaction.InteractionType;
import lol.pyr.znpcsplus.interaction.InteractionActionImpl;
import lol.pyr.znpcsplus.interaction.InteractionActionType;
import lol.pyr.znpcsplus.interaction.InteractionCommandHandler;
import lol.pyr.znpcsplus.scheduling.TaskScheduler;
@ -47,7 +47,7 @@ public class PlayerChatActionType implements InteractionActionType<PlayerChatAct
}
@Override
public InteractionActionImpl parse(CommandContext context) throws CommandExecutionException {
public InteractionAction parse(CommandContext context) throws CommandExecutionException {
InteractionType type = context.parse(InteractionType.class);
long cooldown = (long) (context.parse(Double.class) * 1000D);
long delay = (long) (context.parse(Integer.class) * 1D);

@ -4,7 +4,7 @@ import lol.pyr.director.adventure.command.CommandContext;
import lol.pyr.director.common.command.CommandExecutionException;
import lol.pyr.znpcsplus.api.interaction.InteractionType;
import lol.pyr.znpcsplus.interaction.InteractionActionImpl;
import lol.pyr.znpcsplus.interaction.InteractionActionType;
import lol.pyr.znpcsplus.api.interaction.InteractionActionType;
import lol.pyr.znpcsplus.interaction.InteractionCommandHandler;
import lol.pyr.znpcsplus.scheduling.TaskScheduler;

@ -14,7 +14,7 @@ public class SwitchServerAction extends InteractionActionImpl {
private final String server;
private final BungeeConnector bungeeConnector;
public SwitchServerAction(String server, InteractionType interactionType, long cooldown, long delay, BungeeConnector bungeeConnector) {
public SwitchServerAction(BungeeConnector bungeeConnector, String server, InteractionType interactionType, long cooldown, long delay) {
super(cooldown, delay, interactionType);
this.server = server;
this.bungeeConnector = bungeeConnector;

@ -4,7 +4,7 @@ import lol.pyr.director.adventure.command.CommandContext;
import lol.pyr.director.common.command.CommandExecutionException;
import lol.pyr.znpcsplus.api.interaction.InteractionType;
import lol.pyr.znpcsplus.interaction.InteractionActionImpl;
import lol.pyr.znpcsplus.interaction.InteractionActionType;
import lol.pyr.znpcsplus.api.interaction.InteractionActionType;
import lol.pyr.znpcsplus.interaction.InteractionCommandHandler;
import lol.pyr.znpcsplus.util.BungeeConnector;
@ -29,7 +29,7 @@ public class SwitchServerActionType implements InteractionActionType<SwitchServe
public SwitchServerAction deserialize(String str) {
String[] split = str.split(";");
InteractionType type = split.length > 2 ? InteractionType.valueOf(split[2]) : InteractionType.ANY_CLICK;
return new SwitchServerAction(new String(Base64.getDecoder().decode(split[0]), StandardCharsets.UTF_8), type, Long.parseLong(split[1]), Long.parseLong(split.length > 3 ? split[3] : "0"), bungeeConnector);
return new SwitchServerAction(bungeeConnector, new String(Base64.getDecoder().decode(split[0]), StandardCharsets.UTF_8), type, Long.parseLong(split[1]), Long.parseLong(split.length > 3 ? split[3] : "0"));
}
@Override
@ -53,7 +53,7 @@ public class SwitchServerActionType implements InteractionActionType<SwitchServe
long cooldown = (long) (context.parse(Double.class) * 1000D);
long delay = (long) (context.parse(Integer.class) * 1D);
String server = context.dumpAllArgs();
return new SwitchServerAction(server, type, cooldown, delay, bungeeConnector);
return new SwitchServerAction(bungeeConnector, server, type, cooldown, delay);
}
@Override

@ -3,6 +3,7 @@ package lol.pyr.znpcsplus.npc;
import com.github.retrooper.packetevents.protocol.entity.data.EntityData;
import io.github.retrooper.packetevents.util.SpigotConversionUtil;
import lol.pyr.znpcsplus.api.entity.EntityProperty;
import lol.pyr.znpcsplus.api.interaction.InteractionAction;
import lol.pyr.znpcsplus.api.npc.Npc;
import lol.pyr.znpcsplus.api.npc.NpcType;
import lol.pyr.znpcsplus.config.ConfigManager;
@ -10,7 +11,6 @@ import lol.pyr.znpcsplus.entity.EntityPropertyImpl;
import lol.pyr.znpcsplus.entity.EntityPropertyRegistryImpl;
import lol.pyr.znpcsplus.entity.PacketEntity;
import lol.pyr.znpcsplus.hologram.HologramImpl;
import lol.pyr.znpcsplus.interaction.InteractionActionImpl;
import lol.pyr.znpcsplus.packets.PacketFactory;
import lol.pyr.znpcsplus.util.NpcLocation;
import lol.pyr.znpcsplus.util.Viewable;
@ -36,7 +36,7 @@ public class NpcImpl extends Viewable implements Npc {
private final UUID uuid;
private final Map<EntityPropertyImpl<?>, Object> propertyMap = new HashMap<>();
private final List<InteractionActionImpl> actions = new ArrayList<>();
private final List<InteractionAction> actions = new ArrayList<>();
protected NpcImpl(UUID uuid, EntityPropertyRegistryImpl propertyRegistry, ConfigManager configManager, LegacyComponentSerializer textSerializer, World world, NpcTypeImpl type, NpcLocation location, PacketFactory packetFactory) {
this(uuid, propertyRegistry, configManager, packetFactory, textSerializer, world.getName(), type, location);
@ -200,23 +200,28 @@ public class NpcImpl extends Viewable implements Npc {
return Collections.unmodifiableSet(propertyMap.keySet()).stream().filter(type::isAllowedProperty).collect(Collectors.toSet());
}
public List<InteractionActionImpl> getActions() {
@Override
public List<InteractionAction> getActions() {
return Collections.unmodifiableList(actions);
}
@Override
public void removeAction(int index) {
actions.remove(index);
}
@Override
public void addAction(InteractionAction action) {
actions.add(action);
}
@Override
public void clearActions() {
actions.clear();
}
public void addAction(InteractionActionImpl action) {
actions.add(action);
}
public void editAction(int index, InteractionActionImpl action) {
@Override
public void editAction(int index, InteractionAction action) {
actions.set(index, action);
}

@ -2,6 +2,7 @@ package lol.pyr.znpcsplus.npc;
import lol.pyr.znpcsplus.ZNpcsPlus;
import lol.pyr.znpcsplus.api.entity.EntityProperty;
import lol.pyr.znpcsplus.api.interaction.InteractionAction;
import lol.pyr.znpcsplus.api.npc.NpcEntry;
import lol.pyr.znpcsplus.api.npc.NpcRegistry;
import lol.pyr.znpcsplus.api.npc.NpcType;
@ -10,8 +11,7 @@ import lol.pyr.znpcsplus.entity.EntityPropertyRegistryImpl;
import lol.pyr.znpcsplus.hologram.HologramItem;
import lol.pyr.znpcsplus.hologram.HologramLine;
import lol.pyr.znpcsplus.hologram.HologramText;
import lol.pyr.znpcsplus.interaction.ActionRegistry;
import lol.pyr.znpcsplus.interaction.InteractionActionImpl;
import lol.pyr.znpcsplus.interaction.ActionRegistryImpl;
import lol.pyr.znpcsplus.packets.PacketFactory;
import lol.pyr.znpcsplus.scheduling.TaskScheduler;
import lol.pyr.znpcsplus.storage.NpcStorage;
@ -35,7 +35,7 @@ public class NpcRegistryImpl implements NpcRegistry {
private final Map<String, NpcEntryImpl> npcIdLookupMap = new HashMap<>();
private final Map<UUID, NpcEntryImpl> npcUuidLookupMap = new HashMap<>();
public NpcRegistryImpl(ConfigManager configManager, ZNpcsPlus plugin, PacketFactory packetFactory, ActionRegistry actionRegistry, TaskScheduler scheduler, NpcTypeRegistryImpl typeRegistry, EntityPropertyRegistryImpl propertyRegistry, LegacyComponentSerializer textSerializer) {
public NpcRegistryImpl(ConfigManager configManager, ZNpcsPlus plugin, PacketFactory packetFactory, ActionRegistryImpl actionRegistry, TaskScheduler scheduler, NpcTypeRegistryImpl typeRegistry, EntityPropertyRegistryImpl propertyRegistry, LegacyComponentSerializer textSerializer) {
this.textSerializer = textSerializer;
this.propertyRegistry = propertyRegistry;
storage = configManager.getConfig().storageType().create(configManager, plugin, packetFactory, actionRegistry, typeRegistry, propertyRegistry, textSerializer);
@ -168,7 +168,7 @@ public class NpcRegistryImpl implements NpcRegistry {
newNpc.getNpc().UNSAFE_setProperty(property, oldNpc.getNpc().getProperty(property));
}
for (InteractionActionImpl action : oldNpc.getNpc().getActions()) {
for (InteractionAction action : oldNpc.getNpc().getActions()) {
newNpc.getNpc().addAction(action);
}

@ -370,6 +370,7 @@ public class NpcTypeRegistryImpl implements NpcTypeRegistry {
.setHologramOffset(0.25)
.addProperties("bashing", "camel_sitting"));
if (!version.isNewerThanOrEquals(ServerVersion.V_1_20_5)) return;
register(builder(p, "armadillo", EntityTypes.ARMADILLO)

@ -3,7 +3,7 @@ package lol.pyr.znpcsplus.storage;
import lol.pyr.znpcsplus.ZNpcsPlus;
import lol.pyr.znpcsplus.config.ConfigManager;
import lol.pyr.znpcsplus.entity.EntityPropertyRegistryImpl;
import lol.pyr.znpcsplus.interaction.ActionRegistry;
import lol.pyr.znpcsplus.interaction.ActionRegistryImpl;
import lol.pyr.znpcsplus.npc.NpcTypeRegistryImpl;
import lol.pyr.znpcsplus.packets.PacketFactory;
import lol.pyr.znpcsplus.storage.mysql.MySQLStorage;
@ -16,13 +16,13 @@ import java.io.File;
public enum NpcStorageType {
YAML {
@Override
public NpcStorage create(ConfigManager configManager, ZNpcsPlus plugin, PacketFactory packetFactory, ActionRegistry actionRegistry, NpcTypeRegistryImpl typeRegistry, EntityPropertyRegistryImpl propertyRegistry, LegacyComponentSerializer textSerializer) {
public NpcStorage create(ConfigManager configManager, ZNpcsPlus plugin, PacketFactory packetFactory, ActionRegistryImpl actionRegistry, NpcTypeRegistryImpl typeRegistry, EntityPropertyRegistryImpl propertyRegistry, LegacyComponentSerializer textSerializer) {
return new YamlStorage(packetFactory, configManager, actionRegistry, typeRegistry, propertyRegistry, textSerializer, new File(plugin.getDataFolder(), "data"));
}
},
SQLITE {
@Override
public NpcStorage create(ConfigManager configManager, ZNpcsPlus plugin, PacketFactory packetFactory, ActionRegistry actionRegistry, NpcTypeRegistryImpl typeRegistry, EntityPropertyRegistryImpl propertyRegistry, LegacyComponentSerializer textSerializer) {
public NpcStorage create(ConfigManager configManager, ZNpcsPlus plugin, PacketFactory packetFactory, ActionRegistryImpl actionRegistry, NpcTypeRegistryImpl typeRegistry, EntityPropertyRegistryImpl propertyRegistry, LegacyComponentSerializer textSerializer) {
try {
return new SQLiteStorage(packetFactory, configManager, actionRegistry, typeRegistry, propertyRegistry, textSerializer, new File(plugin.getDataFolder(), "znpcsplus.sqlite"));
} catch (Exception e) {
@ -33,7 +33,7 @@ public enum NpcStorageType {
},
MYSQL {
@Override
public NpcStorage create(ConfigManager configManager, ZNpcsPlus plugin, PacketFactory packetFactory, ActionRegistry actionRegistry, NpcTypeRegistryImpl typeRegistry, EntityPropertyRegistryImpl propertyRegistry, LegacyComponentSerializer textSerializer) {
public NpcStorage create(ConfigManager configManager, ZNpcsPlus plugin, PacketFactory packetFactory, ActionRegistryImpl actionRegistry, NpcTypeRegistryImpl typeRegistry, EntityPropertyRegistryImpl propertyRegistry, LegacyComponentSerializer textSerializer) {
try {
return new MySQLStorage(packetFactory, configManager, actionRegistry, typeRegistry, propertyRegistry, textSerializer);
} catch (Exception e) {
@ -43,5 +43,5 @@ public enum NpcStorageType {
}
};
public abstract NpcStorage create(ConfigManager configManager, ZNpcsPlus plugin, PacketFactory packetFactory, ActionRegistry actionRegistry, NpcTypeRegistryImpl typeRegistry, EntityPropertyRegistryImpl propertyRegistry, LegacyComponentSerializer textSerializer);
public abstract NpcStorage create(ConfigManager configManager, ZNpcsPlus plugin, PacketFactory packetFactory, ActionRegistryImpl actionRegistry, NpcTypeRegistryImpl typeRegistry, EntityPropertyRegistryImpl propertyRegistry, LegacyComponentSerializer textSerializer);
}

@ -6,7 +6,7 @@ import lol.pyr.znpcsplus.entity.EntityPropertyImpl;
import lol.pyr.znpcsplus.entity.EntityPropertyRegistryImpl;
import lol.pyr.znpcsplus.entity.PropertySerializer;
import lol.pyr.znpcsplus.hologram.HologramImpl;
import lol.pyr.znpcsplus.interaction.ActionRegistry;
import lol.pyr.znpcsplus.interaction.ActionRegistryImpl;
import lol.pyr.znpcsplus.npc.NpcEntryImpl;
import lol.pyr.znpcsplus.npc.NpcImpl;
import lol.pyr.znpcsplus.npc.NpcTypeRegistryImpl;
@ -28,7 +28,7 @@ public class MySQLStorage implements NpcStorage {
private final PacketFactory packetFactory;
private final ConfigManager configManager;
private final ActionRegistry actionRegistry;
private final ActionRegistryImpl actionRegistry;
private final NpcTypeRegistryImpl typeRegistry;
private final EntityPropertyRegistryImpl propertyRegistry;
private final LegacyComponentSerializer textSerializer;
@ -39,7 +39,7 @@ public class MySQLStorage implements NpcStorage {
private final String TABLE_NPCS_HOLOGRAMS;
private final String TABLE_NPCS_ACTIONS;
public MySQLStorage(PacketFactory packetFactory, ConfigManager configManager, ActionRegistry actionRegistry, NpcTypeRegistryImpl typeRegistry, EntityPropertyRegistryImpl propertyRegistry, LegacyComponentSerializer textSerializer) {
public MySQLStorage(PacketFactory packetFactory, ConfigManager configManager, ActionRegistryImpl actionRegistry, NpcTypeRegistryImpl typeRegistry, EntityPropertyRegistryImpl propertyRegistry, LegacyComponentSerializer textSerializer) {
this.packetFactory = packetFactory;
this.configManager = configManager;
this.actionRegistry = actionRegistry;

@ -6,7 +6,7 @@ import lol.pyr.znpcsplus.entity.EntityPropertyImpl;
import lol.pyr.znpcsplus.entity.EntityPropertyRegistryImpl;
import lol.pyr.znpcsplus.entity.PropertySerializer;
import lol.pyr.znpcsplus.hologram.HologramImpl;
import lol.pyr.znpcsplus.interaction.ActionRegistry;
import lol.pyr.znpcsplus.interaction.ActionRegistryImpl;
import lol.pyr.znpcsplus.npc.NpcEntryImpl;
import lol.pyr.znpcsplus.npc.NpcImpl;
import lol.pyr.znpcsplus.npc.NpcTypeRegistryImpl;
@ -29,7 +29,7 @@ public class SQLiteStorage implements NpcStorage {
private final PacketFactory packetFactory;
private final ConfigManager configManager;
private final ActionRegistry actionRegistry;
private final ActionRegistryImpl actionRegistry;
private final NpcTypeRegistryImpl typeRegistry;
private final EntityPropertyRegistryImpl propertyRegistry;
private final LegacyComponentSerializer textSerializer;
@ -40,7 +40,7 @@ public class SQLiteStorage implements NpcStorage {
private final String TABLE_NPCS_HOLOGRAMS;
private final String TABLE_NPCS_ACTIONS;
public SQLiteStorage(PacketFactory packetFactory, ConfigManager configManager, ActionRegistry actionRegistry, NpcTypeRegistryImpl typeRegistry, EntityPropertyRegistryImpl propertyRegistry, LegacyComponentSerializer textSerializer, File file) {
public SQLiteStorage(PacketFactory packetFactory, ConfigManager configManager, ActionRegistryImpl actionRegistry, NpcTypeRegistryImpl typeRegistry, EntityPropertyRegistryImpl propertyRegistry, LegacyComponentSerializer textSerializer, File file) {
this.packetFactory = packetFactory;
this.configManager = configManager;
this.actionRegistry = actionRegistry;

@ -6,7 +6,7 @@ import lol.pyr.znpcsplus.entity.EntityPropertyImpl;
import lol.pyr.znpcsplus.entity.EntityPropertyRegistryImpl;
import lol.pyr.znpcsplus.entity.PropertySerializer;
import lol.pyr.znpcsplus.hologram.HologramImpl;
import lol.pyr.znpcsplus.interaction.ActionRegistry;
import lol.pyr.znpcsplus.interaction.ActionRegistryImpl;
import lol.pyr.znpcsplus.npc.NpcEntryImpl;
import lol.pyr.znpcsplus.npc.NpcImpl;
import lol.pyr.znpcsplus.npc.NpcTypeRegistryImpl;
@ -29,13 +29,13 @@ public class YamlStorage implements NpcStorage {
private final PacketFactory packetFactory;
private final ConfigManager configManager;
private final ActionRegistry actionRegistry;
private final ActionRegistryImpl actionRegistry;
private final NpcTypeRegistryImpl typeRegistry;
private final EntityPropertyRegistryImpl propertyRegistry;
private final LegacyComponentSerializer textSerializer;
private final File folder;
public YamlStorage(PacketFactory packetFactory, ConfigManager configManager, ActionRegistry actionRegistry, NpcTypeRegistryImpl typeRegistry, EntityPropertyRegistryImpl propertyRegistry, LegacyComponentSerializer textSerializer, File folder) {
public YamlStorage(PacketFactory packetFactory, ConfigManager configManager, ActionRegistryImpl actionRegistry, NpcTypeRegistryImpl typeRegistry, EntityPropertyRegistryImpl propertyRegistry, LegacyComponentSerializer textSerializer, File folder) {
this.packetFactory = packetFactory;
this.configManager = configManager;
this.actionRegistry = actionRegistry;

@ -0,0 +1,30 @@
package lol.pyr.znpcsplus.user;
import com.github.retrooper.packetevents.event.PacketListener;
import com.github.retrooper.packetevents.event.PacketSendEvent;
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerJoinGame;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerServerData;
import lol.pyr.znpcsplus.config.ConfigManager;
public class ClientPacketListener implements PacketListener {
private final ConfigManager configManager;
public ClientPacketListener(ConfigManager configManager) {
this.configManager = configManager;
}
@Override
public void onPacketSend(PacketSendEvent event) {
if (!configManager.getConfig().fakeEnforceSecureChat()) return;
if (event.getPacketType() == PacketType.Play.Server.SERVER_DATA) {
WrapperPlayServerServerData packet = new WrapperPlayServerServerData(event);
packet.setEnforceSecureChat(true);
event.setByteBuf(packet.getBuffer());
} else if (event.getPacketType() == PacketType.Play.Server.JOIN_GAME) {
WrapperPlayServerJoinGame packet = new WrapperPlayServerJoinGame(event);
packet.setEnforcesSecureChat(true);
event.setByteBuf(packet.getBuffer());
}
}
}

@ -1,3 +1,3 @@
<gray>Usage <gold>» <yellow>/npc center <gold><id>
<gray>Command used to move an npc to the center of the block it's currently occupying
<gray>Command used to move an npc to the center of the block it''s currently occupying

@ -1,3 +1,3 @@
<gray>Usage <gold>» <yellow>/npc setlocation <gold><id> <x> <y> <z>
<gray>Command used to manually adjust an npc's location
<gray>Command used to manually adjust an npc''s location

@ -1,3 +1,3 @@
<gray>Usage <gold>» <yellow>/npc setrotation <gold><id> <yaw> <pitch>
<gray>Command used to manually adjust an npc's rotation
<gray>Command used to manually adjust an npc''s rotation