├── .github └── znpc.png ├── .gitignore ├── LICENSE ├── README.md ├── api ├── build.gradle └── src │ └── main │ └── java │ └── lol │ └── pyr │ └── znpcsplus │ ├── api │ ├── NpcApi.java │ ├── NpcApiProvider.java │ ├── NpcPropertyRegistryProvider.java │ ├── entity │ │ ├── EntityProperty.java │ │ ├── EntityPropertyRegistry.java │ │ └── PropertyHolder.java │ ├── event │ │ ├── NpcDespawnEvent.java │ │ ├── NpcInteractEvent.java │ │ ├── NpcSpawnEvent.java │ │ └── util │ │ │ ├── CancellableNpcEvent.java │ │ │ └── NpcEvent.java │ ├── hologram │ │ └── Hologram.java │ ├── interaction │ │ ├── ActionFactory.java │ │ ├── ActionRegistry.java │ │ ├── InteractionAction.java │ │ ├── InteractionActionType.java │ │ └── InteractionType.java │ ├── npc │ │ ├── Npc.java │ │ ├── NpcEntry.java │ │ ├── NpcRegistry.java │ │ ├── NpcType.java │ │ └── NpcTypeRegistry.java │ ├── serialization │ │ ├── NpcSerializer.java │ │ └── NpcSerializerRegistry.java │ └── skin │ │ ├── Skin.java │ │ ├── SkinDescriptor.java │ │ └── SkinDescriptorFactory.java │ └── util │ ├── ArmadilloState.java │ ├── AttachDirection.java │ ├── AxolotlVariant.java │ ├── BlockState.java │ ├── CatVariant.java │ ├── CreeperState.java │ ├── FoxVariant.java │ ├── FrogVariant.java │ ├── HorseArmor.java │ ├── HorseColor.java │ ├── HorseStyle.java │ ├── HorseType.java │ ├── LlamaVariant.java │ ├── LookType.java │ ├── MooshroomVariant.java │ ├── NamedColor.java │ ├── NpcLocation.java │ ├── NpcPose.java │ ├── OcelotType.java │ ├── PandaGene.java │ ├── ParrotVariant.java │ ├── PuffState.java │ ├── RabbitType.java │ ├── SkeletonType.java │ ├── SnifferState.java │ ├── SpellType.java │ ├── TropicalFishVariant.java │ ├── Vector3f.java │ ├── Vector3i.java │ ├── VillagerLevel.java │ ├── VillagerProfession.java │ ├── VillagerType.java │ ├── WoldVariant.java │ └── ZombieType.java ├── build.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── plugin ├── build.gradle └── src │ └── main │ ├── java │ └── lol │ │ └── pyr │ │ └── znpcsplus │ │ ├── ZNpcsPlus.java │ │ ├── ZNpcsPlusApi.java │ │ ├── ZNpcsPlusBootstrap.java │ │ ├── commands │ │ ├── CenterCommand.java │ │ ├── ChangeIdCommand.java │ │ ├── CloneCommand.java │ │ ├── CreateCommand.java │ │ ├── DeleteCommand.java │ │ ├── ListCommand.java │ │ ├── LookAtMeCommand.java │ │ ├── MoveCommand.java │ │ ├── NearCommand.java │ │ ├── ReloadConfigCommand.java │ │ ├── SetLocationCommand.java │ │ ├── SetRotationCommand.java │ │ ├── SkinCommand.java │ │ ├── TeleportCommand.java │ │ ├── ToggleCommand.java │ │ ├── TypeCommand.java │ │ ├── VersionCommand.java │ │ ├── action │ │ │ ├── ActionAddCommand.java │ │ │ ├── ActionClearCommand.java │ │ │ ├── ActionDeleteCommand.java │ │ │ ├── ActionEditCommand.java │ │ │ └── ActionListCommand.java │ │ ├── hologram │ │ │ ├── HoloAddCommand.java │ │ │ ├── HoloAddItemCommand.java │ │ │ ├── HoloDeleteCommand.java │ │ │ ├── HoloInfoCommand.java │ │ │ ├── HoloInsertCommand.java │ │ │ ├── HoloInsertItemCommand.java │ │ │ ├── HoloOffsetCommand.java │ │ │ ├── HoloRefreshDelayCommand.java │ │ │ ├── HoloSetCommand.java │ │ │ └── HoloSetItemCommand.java │ │ ├── property │ │ │ ├── PropertyRemoveCommand.java │ │ │ └── PropertySetCommand.java │ │ └── storage │ │ │ ├── ImportCommand.java │ │ │ ├── LoadAllCommand.java │ │ │ ├── MigrateCommand.java │ │ │ └── SaveAllCommand.java │ │ ├── config │ │ ├── ComponentSerializer.java │ │ ├── ConfigManager.java │ │ ├── DatabaseConfig.java │ │ ├── MainConfig.java │ │ └── MessageConfig.java │ │ ├── conversion │ │ ├── DataImporter.java │ │ ├── DataImporterRegistry.java │ │ ├── citizens │ │ │ ├── CitizensImporter.java │ │ │ └── model │ │ │ │ ├── CitizensTrait.java │ │ │ │ ├── CitizensTraitsRegistry.java │ │ │ │ ├── SectionCitizensTrait.java │ │ │ │ ├── StringCitizensTrait.java │ │ │ │ └── traits │ │ │ │ ├── CommandTrait.java │ │ │ │ ├── EquipmentTrait.java │ │ │ │ ├── HologramTrait.java │ │ │ │ ├── LocationTrait.java │ │ │ │ ├── LookTrait.java │ │ │ │ ├── MirrorTrait.java │ │ │ │ ├── ProfessionTrait.java │ │ │ │ ├── SkinLayersTrait.java │ │ │ │ ├── SkinTrait.java │ │ │ │ ├── SpawnedTrait.java │ │ │ │ ├── TypeTrait.java │ │ │ │ └── VillagerTrait.java │ │ ├── fancynpcs │ │ │ └── FancyNpcsImporter.java │ │ └── znpcs │ │ │ ├── ZNpcImporter.java │ │ │ └── model │ │ │ ├── ZNpcsAction.java │ │ │ ├── ZNpcsConversation.java │ │ │ ├── ZNpcsConversationText.java │ │ │ ├── ZNpcsLocation.java │ │ │ ├── ZNpcsModel.java │ │ │ └── ZnpcsConversations.java │ │ ├── entity │ │ ├── ArmorStandVehicleProperties.java │ │ ├── EntityPropertyImpl.java │ │ ├── EntityPropertyRegistryImpl.java │ │ ├── EnumPropertySerializer.java │ │ ├── PacketEntity.java │ │ ├── ParrotNBTCompound.java │ │ ├── PrimitivePropertySerializer.java │ │ ├── PropertySerializer.java │ │ ├── properties │ │ │ ├── BitsetProperty.java │ │ │ ├── BooleanProperty.java │ │ │ ├── CamelSittingProperty.java │ │ │ ├── CustomTypeProperty.java │ │ │ ├── DinnerboneProperty.java │ │ │ ├── DummyProperty.java │ │ │ ├── EncodedByteProperty.java │ │ │ ├── EncodedIntegerProperty.java │ │ │ ├── EncodedStringProperty.java │ │ │ ├── EntitySittingProperty.java │ │ │ ├── EquipmentProperty.java │ │ │ ├── ForceBodyRotationProperty.java │ │ │ ├── GlowProperty.java │ │ │ ├── HealthProperty.java │ │ │ ├── HologramItemProperty.java │ │ │ ├── HorseColorProperty.java │ │ │ ├── HorseStyleProperty.java │ │ │ ├── IntegerProperty.java │ │ │ ├── LegacyBabyProperty.java │ │ │ ├── NBTProperty.java │ │ │ ├── NameProperty.java │ │ │ ├── OptionalBlockPosProperty.java │ │ │ ├── RabbitTypeProperty.java │ │ │ ├── RotationProperty.java │ │ │ ├── TargetNpcProperty.java │ │ │ ├── TropicalFishVariantProperty.java │ │ │ ├── attributes │ │ │ │ └── AttributeProperty.java │ │ │ └── villager │ │ │ │ ├── VillagerDataProperty.java │ │ │ │ ├── VillagerLevelProperty.java │ │ │ │ ├── VillagerProfessionProperty.java │ │ │ │ └── VillagerTypeProperty.java │ │ └── serializers │ │ │ ├── BlockStatePropertySerializer.java │ │ │ ├── BooleanPropertySerializer.java │ │ │ ├── ColorPropertySerializer.java │ │ │ ├── ComponentPropertySerializer.java │ │ │ ├── GenericSerializer.java │ │ │ ├── ItemStackPropertySerializer.java │ │ │ ├── LookTypeSerializer.java │ │ │ ├── NamedColorPropertySerializer.java │ │ │ ├── SkinDescriptorSerializer.java │ │ │ ├── TargetNpcPropertySerializer.java │ │ │ └── Vector3fPropertySerializer.java │ │ ├── hologram │ │ ├── HologramImpl.java │ │ ├── HologramItem.java │ │ ├── HologramLine.java │ │ └── HologramText.java │ │ ├── interaction │ │ ├── ActionFactoryImpl.java │ │ ├── ActionRegistryImpl.java │ │ ├── InteractionActionImpl.java │ │ ├── InteractionCommandHandler.java │ │ ├── InteractionPacketListener.java │ │ ├── consolecommand │ │ │ ├── ConsoleCommandAction.java │ │ │ └── ConsoleCommandActionType.java │ │ ├── message │ │ │ ├── MessageAction.java │ │ │ └── MessageActionType.java │ │ ├── playerchat │ │ │ ├── PlayerChatAction.java │ │ │ └── PlayerChatActionType.java │ │ ├── playercommand │ │ │ ├── PlayerCommandAction.java │ │ │ └── PlayerCommandActionType.java │ │ └── switchserver │ │ │ ├── SwitchServerAction.java │ │ │ └── SwitchServerActionType.java │ │ ├── npc │ │ ├── NpcEntryImpl.java │ │ ├── NpcImpl.java │ │ ├── NpcRegistryImpl.java │ │ ├── NpcTypeImpl.java │ │ └── NpcTypeRegistryImpl.java │ │ ├── packets │ │ ├── PacketFactory.java │ │ ├── V1_17PacketFactory.java │ │ ├── V1_19_3PacketFactory.java │ │ ├── V1_20_2PacketFactory.java │ │ ├── V1_21_3PacketFactory.java │ │ └── V1_8PacketFactory.java │ │ ├── parsers │ │ ├── ColorParser.java │ │ ├── EntityPropertyParser.java │ │ ├── EnumParser.java │ │ ├── InteractionTypeParser.java │ │ ├── NamedColorParser.java │ │ ├── NpcEntryParser.java │ │ ├── NpcTypeParser.java │ │ ├── StringParser.java │ │ ├── Vector3fParser.java │ │ └── Vector3iParser.java │ │ ├── reflection │ │ ├── ReflectionBuilder.java │ │ ├── ReflectionLazyLoader.java │ │ ├── ReflectionPackage.java │ │ ├── Reflections.java │ │ └── types │ │ │ ├── ClassReflection.java │ │ │ ├── FieldReflection.java │ │ │ └── MethodReflection.java │ │ ├── scheduling │ │ ├── FoliaScheduler.java │ │ ├── SpigotScheduler.java │ │ └── TaskScheduler.java │ │ ├── serialization │ │ ├── NpcSerializerRegistryImpl.java │ │ └── YamlSerializer.java │ │ ├── skin │ │ ├── BaseSkinDescriptor.java │ │ ├── SkinDescriptorFactoryImpl.java │ │ ├── SkinImpl.java │ │ ├── cache │ │ │ ├── CachedId.java │ │ │ ├── MojangSkinCache.java │ │ │ └── SkinCacheCleanTask.java │ │ └── descriptor │ │ │ ├── MirrorDescriptor.java │ │ │ ├── NameFetchingDescriptor.java │ │ │ ├── PrefetchedDescriptor.java │ │ │ └── UUIDFetchingDescriptor.java │ │ ├── storage │ │ ├── NpcStorage.java │ │ ├── NpcStorageType.java │ │ ├── database │ │ │ └── Database.java │ │ ├── mysql │ │ │ ├── MySQL.java │ │ │ └── MySQLStorage.java │ │ ├── sqlite │ │ │ ├── SQLite.java │ │ │ └── SQLiteStorage.java │ │ └── yaml │ │ │ └── YamlStorage.java │ │ ├── tasks │ │ ├── HologramRefreshTask.java │ │ ├── NpcProcessorTask.java │ │ └── ViewableHideOnLeaveListener.java │ │ ├── updater │ │ ├── UpdateChecker.java │ │ └── UpdateNotificationListener.java │ │ ├── user │ │ ├── ClientPacketListener.java │ │ ├── User.java │ │ ├── UserListener.java │ │ └── UserManager.java │ │ └── util │ │ ├── BungeeConnector.java │ │ ├── FileUtil.java │ │ ├── FoliaUtil.java │ │ ├── FutureUtil.java │ │ ├── ItemSerializationUtil.java │ │ ├── LazyLoader.java │ │ ├── PapiUtil.java │ │ └── Viewable.java │ └── resources │ ├── messages │ ├── action-hover │ │ ├── add.txt │ │ ├── clear.txt │ │ ├── delete.txt │ │ ├── edit.txt │ │ └── list.txt │ ├── action.txt │ ├── holo-hover │ │ ├── add.txt │ │ ├── additem.txt │ │ ├── delete.txt │ │ ├── info.txt │ │ ├── insert.txt │ │ ├── insertitem.txt │ │ ├── offset.txt │ │ ├── refreshdelay.txt │ │ ├── set.txt │ │ └── setitem.txt │ ├── holo.txt │ ├── property-hover │ │ ├── remove.txt │ │ └── set.txt │ ├── property.txt │ ├── root-hover │ │ ├── center.txt │ │ ├── changeid.txt │ │ ├── create.txt │ │ ├── delete.txt │ │ ├── list.txt │ │ ├── lookatme.txt │ │ ├── move.txt │ │ ├── near.txt │ │ ├── setlocation.txt │ │ ├── setrotation.txt │ │ ├── skin.txt │ │ ├── teleport.txt │ │ ├── toggle.txt │ │ └── type.txt │ ├── root.txt │ ├── storage-hover │ │ ├── import.txt │ │ ├── migrate.txt │ │ ├── reload.txt │ │ └── save.txt │ └── storage.txt │ └── plugin.yml └── settings.gradle /.github/znpc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pyrbu/ZNPCsPlus/63db907d325730e73367de4ce17133df2697ba76/.github/znpc.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | !**/src/main/**/build/ 5 | !**/src/test/**/build/ 6 | 7 | ### IntelliJ IDEA ### 8 | /.idea/* 9 | .idea/modules.xml 10 | .idea/jarRepositories.xml 11 | .idea/compiler.xml 12 | .idea/libraries/ 13 | *.iws 14 | *.iml 15 | *.ipr 16 | out/ 17 | !**/src/main/**/out/ 18 | !**/src/test/**/out/ 19 | 20 | ### Eclipse ### 21 | .apt_generated 22 | .classpath 23 | .factorypath 24 | .project 25 | .settings 26 | .springBeans 27 | .sts4-cache 28 | bin/ 29 | !**/src/main/**/bin/ 30 | !**/src/test/**/bin/ 31 | 32 | ### NetBeans ### 33 | /nbproject/private/ 34 | /nbbuild/ 35 | /dist/ 36 | /nbdist/ 37 | /.nb-gradle/ 38 | 39 | ### VS Code ### 40 | .vscode/ 41 | 42 | ### Mac OS ### 43 | .DS_Store 44 | 45 | /plugin/run/ 46 | /.idea/ 47 | -------------------------------------------------------------------------------- /api/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id "java" 3 | id "maven-publish" 4 | } 5 | 6 | java { 7 | withSourcesJar() 8 | withJavadocJar() 9 | } 10 | 11 | publishing { 12 | publications { 13 | mavenJava(MavenPublication) { 14 | from components.java 15 | artifactId = "znpcsplus-api" 16 | 17 | pom { 18 | name.set("znpcsplus-api") 19 | description.set("The API for the ZNPCsPlus plugin") 20 | url.set("https://github.com/Pyrbu/ZNPCsPlus") 21 | } 22 | } 23 | } 24 | repositories { 25 | maven { 26 | Map systemProperties = System.getenv() 27 | credentials { 28 | if (systemProperties.containsKey("DIST_USERNAME")) username systemProperties.get("DIST_USERNAME") 29 | if (systemProperties.containsKey("DIST_PASSWORD")) password systemProperties.get("DIST_PASSWORD") 30 | } 31 | // If the BUILD_ID enviroment variable is present that means its a Jenkins build & that it should go into the snapshots repo 32 | url = systemProperties.containsKey("BUILD_ID") ? uri("https://repo.pyr.lol/snapshots/") : uri("https://repo.pyr.lol/releases/") 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /api/src/main/java/lol/pyr/znpcsplus/api/NpcApi.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.api; 2 | 3 | import lol.pyr.znpcsplus.api.entity.EntityPropertyRegistry; 4 | import lol.pyr.znpcsplus.api.interaction.ActionFactory; 5 | import lol.pyr.znpcsplus.api.interaction.ActionRegistry; 6 | import lol.pyr.znpcsplus.api.npc.NpcRegistry; 7 | import lol.pyr.znpcsplus.api.npc.NpcTypeRegistry; 8 | import lol.pyr.znpcsplus.api.serialization.NpcSerializerRegistry; 9 | import lol.pyr.znpcsplus.api.skin.SkinDescriptorFactory; 10 | 11 | /** 12 | * Main API class for ZNPCsPlus. 13 | */ 14 | public interface NpcApi { 15 | /** 16 | * Gets the NPC registry. 17 | * @return the NPC registry 18 | */ 19 | NpcRegistry getNpcRegistry(); 20 | 21 | /** 22 | * Gets the NPC type registry. 23 | * @return the NPC type registry 24 | */ 25 | NpcTypeRegistry getNpcTypeRegistry(); 26 | 27 | /** 28 | * Gets the entity property registry. 29 | * @return the entity property registry 30 | */ 31 | EntityPropertyRegistry getPropertyRegistry(); 32 | 33 | /** 34 | * Gets the action registry. 35 | * @return the action registry 36 | */ 37 | ActionRegistry getActionRegistry(); 38 | 39 | /** 40 | * Gets the action factory. 41 | * @return the action factory 42 | */ 43 | ActionFactory getActionFactory(); 44 | 45 | /** 46 | * Gets the skin descriptor factory. 47 | * @return the skin descriptor factory 48 | */ 49 | SkinDescriptorFactory getSkinDescriptorFactory(); 50 | 51 | /** 52 | * Gets the npc serializer registry. 53 | * @return the npc serializer registry 54 | */ 55 | NpcSerializerRegistry getNpcSerializerRegistry(); 56 | } 57 | -------------------------------------------------------------------------------- /api/src/main/java/lol/pyr/znpcsplus/api/NpcApiProvider.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.api; 2 | 3 | import org.bukkit.Bukkit; 4 | import org.bukkit.plugin.Plugin; 5 | import org.bukkit.plugin.ServicePriority; 6 | 7 | /** 8 | * Provider for the registered api instance 9 | */ 10 | public class NpcApiProvider { 11 | private static NpcApi api = null; 12 | 13 | private NpcApiProvider() { 14 | throw new UnsupportedOperationException(); 15 | } 16 | 17 | /** 18 | * Static method that returns the api instance of the plugin 19 | * 20 | * @return The instance of the api for the ZNPCsPlus plugin 21 | */ 22 | public static NpcApi get() { 23 | if (api == null) throw new IllegalStateException( 24 | "ZNPCsPlus plugin isn't enabled yet!\n" + 25 | "Please add it to your plugin.yml as a depend or softdepend." 26 | ); 27 | return api; 28 | } 29 | 30 | /** 31 | * Internal method used to register the main instance of the plugin as the api provider 32 | * You probably shouldn't call this method under any circumstances 33 | * 34 | * @param plugin Instance of the ZNPCsPlus plugin 35 | * @param api Instance of the ZNPCsPlus api 36 | */ 37 | public static void register(Plugin plugin, NpcApi api) { 38 | NpcApiProvider.api = api; 39 | Bukkit.getServicesManager().register(NpcApi.class, api, plugin, ServicePriority.Normal); 40 | } 41 | 42 | /** 43 | * Internal method used to unregister the plugin from the provider when the plugin shuts down 44 | * You probably shouldn't call this method under any circumstances 45 | */ 46 | public static void unregister() { 47 | Bukkit.getServicesManager().unregister(api); 48 | NpcApiProvider.api = null; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /api/src/main/java/lol/pyr/znpcsplus/api/NpcPropertyRegistryProvider.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.api; 2 | 3 | import lol.pyr.znpcsplus.api.entity.EntityPropertyRegistry; 4 | import org.bukkit.Bukkit; 5 | import org.bukkit.plugin.Plugin; 6 | import org.bukkit.plugin.ServicePriority; 7 | 8 | /** 9 | * Provider for the registered entity property registry instance 10 | */ 11 | public class NpcPropertyRegistryProvider { 12 | private static EntityPropertyRegistry registry = null; 13 | 14 | private NpcPropertyRegistryProvider() { 15 | throw new UnsupportedOperationException(); 16 | } 17 | 18 | /** 19 | * Static method that returns the entity property registry instance of the plugin 20 | * 21 | * @return The instance of the entity property registry for the ZNPCsPlus plugin 22 | */ 23 | public static EntityPropertyRegistry get() { 24 | if (registry == null) throw new IllegalStateException( 25 | "ZNPCsPlus plugin isn't loaded yet!\n" + 26 | "Please add it to your plugin.yml as a depend or softdepend." 27 | ); 28 | return registry; 29 | } 30 | 31 | /** 32 | * Internal method used to register the main instance of the plugin as the entity property registry provider 33 | * You probably shouldn't call this method under any circumstances 34 | * 35 | * @param plugin Instance of the ZNPCsPlus plugin 36 | * @param api Instance of the ZNPCsPlus entity property registry 37 | */ 38 | public static void register(Plugin plugin, EntityPropertyRegistry api) { 39 | NpcPropertyRegistryProvider.registry = api; 40 | Bukkit.getServicesManager().register(EntityPropertyRegistry.class, registry, plugin, ServicePriority.Normal); 41 | } 42 | 43 | /** 44 | * Internal method used to unregister the plugin from the provider when the plugin shuts down 45 | * You probably shouldn't call this method under any circumstances 46 | */ 47 | public static void unregister() { 48 | Bukkit.getServicesManager().unregister(registry); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /api/src/main/java/lol/pyr/znpcsplus/api/entity/EntityProperty.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.api.entity; 2 | 3 | /** 4 | * Class that represents a unique property 5 | * @param The type of the value of this property 6 | */ 7 | public interface EntityProperty { 8 | /** 9 | * The default value of this property, if this is provided in {@link PropertyHolder#setProperty(EntityProperty, Object)} 10 | * as the value the property will be removed from the holder 11 | * 12 | * @return The default value of this property 13 | */ 14 | T getDefaultValue(); 15 | 16 | /** 17 | * @return The name of this property 18 | */ 19 | String getName(); 20 | 21 | /** 22 | * @return Whether this property can be modified by players using commands 23 | */ 24 | boolean isPlayerModifiable(); 25 | } 26 | -------------------------------------------------------------------------------- /api/src/main/java/lol/pyr/znpcsplus/api/event/NpcDespawnEvent.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.api.event; 2 | 3 | import lol.pyr.znpcsplus.api.event.util.CancellableNpcEvent; 4 | import lol.pyr.znpcsplus.api.npc.NpcEntry; 5 | import org.bukkit.entity.Player; 6 | import org.bukkit.event.Cancellable; 7 | import org.bukkit.event.HandlerList; 8 | 9 | /** 10 | * Event called when an NPC is despawned for a player 11 | * Note: This event is async 12 | */ 13 | public class NpcDespawnEvent extends CancellableNpcEvent implements Cancellable { 14 | private static final HandlerList handlers = new HandlerList(); 15 | 16 | /** 17 | * @param player The player involved in the event 18 | * @param entry The NPC entry involved in the event 19 | */ 20 | public NpcDespawnEvent(Player player, NpcEntry entry) { 21 | super(player, entry); 22 | } 23 | 24 | @Override 25 | public HandlerList getHandlers() { 26 | return handlers; 27 | } 28 | 29 | public static HandlerList getHandlerList() { 30 | return handlers; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /api/src/main/java/lol/pyr/znpcsplus/api/event/NpcInteractEvent.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.api.event; 2 | 3 | import lol.pyr.znpcsplus.api.event.util.CancellableNpcEvent; 4 | import lol.pyr.znpcsplus.api.interaction.InteractionType; 5 | import lol.pyr.znpcsplus.api.npc.NpcEntry; 6 | import org.bukkit.entity.Player; 7 | import org.bukkit.event.Cancellable; 8 | import org.bukkit.event.HandlerList; 9 | 10 | /** 11 | * Event called when an NPC is interacted with by a player 12 | * Note: This event is async 13 | */ 14 | public class NpcInteractEvent extends CancellableNpcEvent implements Cancellable { 15 | private static final HandlerList handlers = new HandlerList(); 16 | 17 | private final InteractionType clickType; 18 | 19 | /** 20 | * @param player The player involved in the event 21 | * @param entry The NPC entry involved in the event 22 | * @param clickType The type of interaction. See {@link InteractionType} 23 | */ 24 | public NpcInteractEvent(Player player, NpcEntry entry, InteractionType clickType) { 25 | super(player, entry); 26 | this.clickType = clickType; 27 | } 28 | 29 | @Override 30 | public HandlerList getHandlers() { 31 | return handlers; 32 | } 33 | 34 | /** 35 | * Returns the type of interaction. See {@link InteractionType} 36 | * @return The type of interaction 37 | */ 38 | public InteractionType getClickType() { 39 | return clickType; 40 | } 41 | 42 | public static HandlerList getHandlerList() { 43 | return handlers; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /api/src/main/java/lol/pyr/znpcsplus/api/event/NpcSpawnEvent.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.api.event; 2 | 3 | import lol.pyr.znpcsplus.api.event.util.CancellableNpcEvent; 4 | import lol.pyr.znpcsplus.api.npc.NpcEntry; 5 | import org.bukkit.entity.Player; 6 | import org.bukkit.event.Cancellable; 7 | import org.bukkit.event.HandlerList; 8 | 9 | /** 10 | * Event called when an NPC is spawned for a player 11 | * Note: This event is async 12 | */ 13 | public class NpcSpawnEvent extends CancellableNpcEvent implements Cancellable { 14 | private static final HandlerList handlers = new HandlerList(); 15 | 16 | /** 17 | * @param player The player involved in the event 18 | * @param entry The NPC entry involved in the event 19 | */ 20 | public NpcSpawnEvent(Player player, NpcEntry entry) { 21 | super(player, entry); 22 | } 23 | 24 | @Override 25 | public HandlerList getHandlers() { 26 | return handlers; 27 | } 28 | 29 | public static HandlerList getHandlerList() { 30 | return handlers; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /api/src/main/java/lol/pyr/znpcsplus/api/event/util/CancellableNpcEvent.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.api.event.util; 2 | 3 | import lol.pyr.znpcsplus.api.npc.NpcEntry; 4 | import org.bukkit.entity.Player; 5 | import org.bukkit.event.Cancellable; 6 | 7 | /** 8 | * Base class for all NPC events that can be cancelled 9 | */ 10 | public abstract class CancellableNpcEvent extends NpcEvent implements Cancellable { 11 | private boolean cancelled = false; 12 | 13 | /** 14 | * @param player The player involved in the event 15 | * @param entry The NPC entry involved in the event 16 | */ 17 | public CancellableNpcEvent(Player player, NpcEntry entry) { 18 | super(player, entry); 19 | } 20 | 21 | @Override 22 | public boolean isCancelled() { 23 | return cancelled; 24 | } 25 | 26 | @Override 27 | public void setCancelled(boolean cancel) { 28 | cancelled = cancel; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /api/src/main/java/lol/pyr/znpcsplus/api/event/util/NpcEvent.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.api.event.util; 2 | 3 | import lol.pyr.znpcsplus.api.npc.Npc; 4 | import lol.pyr.znpcsplus.api.npc.NpcEntry; 5 | import org.bukkit.entity.Player; 6 | import org.bukkit.event.Event; 7 | 8 | /** 9 | * Base class for all NPC events 10 | */ 11 | public abstract class NpcEvent extends Event { 12 | private final NpcEntry entry; 13 | private final Player player; 14 | 15 | /** 16 | * @param player The player involved in the event 17 | * @param entry The NPC entry involved in the event 18 | */ 19 | public NpcEvent(Player player, NpcEntry entry) { 20 | super(true); // All events are async since 99% of the plugin is async 21 | this.entry = entry; 22 | this.player = player; 23 | } 24 | 25 | /** 26 | * Returns the player involved in the event 27 | * @return The player involved in the event 28 | */ 29 | public Player getPlayer() { 30 | return player; 31 | } 32 | 33 | /** 34 | * Returns the NPC entry involved in the event 35 | * @return The NPC entry involved in the event 36 | */ 37 | public NpcEntry getEntry() { 38 | return entry; 39 | } 40 | 41 | /** 42 | * Returns the NPC involved in the event 43 | * @return The NPC involved in the event 44 | */ 45 | public Npc getNpc() { 46 | return entry.getNpc(); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /api/src/main/java/lol/pyr/znpcsplus/api/hologram/Hologram.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.api.hologram; 2 | 3 | /** 4 | * Represents a hologram 5 | */ 6 | public interface Hologram { 7 | /** 8 | * Adds a line to the hologram 9 | * Note: to add an item line, pass "item:<item>" as the line 10 | * @param line The line to add 11 | */ 12 | void addLine(String line); 13 | 14 | /** 15 | * Gets a line from the hologram 16 | * @param index The index of the line to get 17 | * @return The line at the index 18 | */ 19 | String getLine(int index); 20 | 21 | /** 22 | * Removes a line from the hologram 23 | * @param index The index of the line to remove 24 | */ 25 | void removeLine(int index); 26 | 27 | /** 28 | * Clears all lines from the hologram 29 | */ 30 | void clearLines(); 31 | 32 | /** 33 | * Inserts a line into the hologram 34 | * @param index The index to insert the line at 35 | * @param line The line to insert 36 | */ 37 | void insertLine(int index, String line); 38 | 39 | /** 40 | * Gets the number of lines in the hologram 41 | * @return The number of lines in the hologram 42 | */ 43 | int lineCount(); 44 | 45 | /** 46 | * Gets the refresh delay of the hologram 47 | * @return The refresh delay of the hologram 48 | */ 49 | long getRefreshDelay(); 50 | 51 | /** 52 | * Sets the refresh delay of the hologram 53 | * @param delay The delay to set 54 | */ 55 | void setRefreshDelay(long delay); 56 | } 57 | -------------------------------------------------------------------------------- /api/src/main/java/lol/pyr/znpcsplus/api/interaction/ActionFactory.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.api.interaction; 2 | 3 | @SuppressWarnings("unused") 4 | public interface ActionFactory { 5 | InteractionAction createConsoleCommandAction(String command, InteractionType interactionType, long cooldown, long delay); 6 | InteractionAction createMessageAction(String message, InteractionType interactionType, long cooldown, long delay); 7 | InteractionAction createPlayerChatAction(String message, InteractionType interactionType, long cooldown, long delay); 8 | InteractionAction createPlayerCommandAction(String command, InteractionType interactionType, long cooldown, long delay); 9 | InteractionAction createSwitchServerAction(String server, InteractionType interactionType, long cooldown, long delay); 10 | } 11 | -------------------------------------------------------------------------------- /api/src/main/java/lol/pyr/znpcsplus/api/interaction/ActionRegistry.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.api.interaction; 2 | 3 | public interface ActionRegistry { 4 | void register(InteractionActionType type); 5 | 6 | void unregister(Class clazz); 7 | } 8 | -------------------------------------------------------------------------------- /api/src/main/java/lol/pyr/znpcsplus/api/interaction/InteractionActionType.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.api.interaction; 2 | 3 | public interface InteractionActionType { 4 | String serialize(T obj); 5 | T deserialize(String str); 6 | Class getActionClass(); 7 | } 8 | -------------------------------------------------------------------------------- /api/src/main/java/lol/pyr/znpcsplus/api/interaction/InteractionType.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.api.interaction; 2 | 3 | /** 4 | * The type of interaction 5 | * ANY_CLICK: Any click type 6 | * LEFT_CLICK: Only left clicks 7 | * RIGHT_CLICK: Only right clicks 8 | */ 9 | public enum InteractionType { 10 | ANY_CLICK, 11 | LEFT_CLICK, 12 | RIGHT_CLICK 13 | } 14 | -------------------------------------------------------------------------------- /api/src/main/java/lol/pyr/znpcsplus/api/npc/NpcEntry.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.api.npc; 2 | 3 | /** 4 | * Base class for all NPC entries 5 | * An NPC entry is a wrapper around an NPC that contains additional information 6 | */ 7 | public interface NpcEntry { 8 | /** 9 | * Gets the ID of this NPC entry 10 | * @return The ID of this NPC entry 11 | */ 12 | String getId(); 13 | /** 14 | * Gets the NPC of this NPC entry 15 | * @return The {@link Npc} of this NPC entry 16 | */ 17 | Npc getNpc(); 18 | 19 | /** 20 | * Gets if this NPC entry is processed or not 21 | * @return If this NPC entry is processed or not 22 | */ 23 | boolean isProcessed(); 24 | /** 25 | * Sets if this NPC entry is processed or not 26 | * @param value If this NPC entry is processed or not 27 | */ 28 | void setProcessed(boolean value); 29 | 30 | /** 31 | * @return If this NPC entry SHOULD be saved into the storage or not 32 | */ 33 | boolean isSave(); 34 | /** 35 | * Sets if this NPC should be saved or not 36 | * @param value If this NPC entry should be saved or not 37 | */ 38 | void setSave(boolean value); 39 | 40 | /** 41 | * Gets if this NPC can be modified by commands 42 | * @return {@code true} if this NPC can be modified by commands, {@code false} otherwise 43 | */ 44 | boolean isAllowCommandModification(); 45 | /** 46 | * Sets if this NPC can be modified by commands 47 | * @param value {@code true} if this NPC can be modified by commands, {@code false} otherwise 48 | */ 49 | void setAllowCommandModification(boolean value); 50 | 51 | /** 52 | * Enables everything for this NPC entry 53 | * That is, it makes the NPC processed, saveable, and allows command modification 54 | */ 55 | void enableEverything(); 56 | } 57 | -------------------------------------------------------------------------------- /api/src/main/java/lol/pyr/znpcsplus/api/npc/NpcType.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.api.npc; 2 | 3 | import lol.pyr.znpcsplus.api.entity.EntityProperty; 4 | 5 | import java.util.Set; 6 | 7 | /** 8 | * Represents a type of NPC. 9 | * This defines the {@link org.bukkit.entity.EntityType} of the NPC, as well as the properties that are allowed to be set on the NPC. 10 | */ 11 | public interface NpcType { 12 | /** 13 | * The name of the NPC type. 14 | * @return The name of the NPC type. 15 | */ 16 | String getName(); 17 | 18 | /** 19 | * The offset of the hologram above the NPC. 20 | * @return the offset 21 | */ 22 | double getHologramOffset(); 23 | 24 | /** 25 | * Set of properties that are allowed to be set on the NPC. 26 | * @return allowed properties 27 | */ 28 | Set> getAllowedProperties(); 29 | } 30 | -------------------------------------------------------------------------------- /api/src/main/java/lol/pyr/znpcsplus/api/npc/NpcTypeRegistry.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.api.npc; 2 | 3 | import java.util.Collection; 4 | 5 | /** 6 | * Base for NpcType registries. 7 | */ 8 | public interface NpcTypeRegistry { 9 | /** 10 | * Gets a NPC type by name. 11 | * @param name The name of the NPC type. 12 | * @return The type that is represented by the name or null if it doesnt exist 13 | */ 14 | NpcType getByName(String name); 15 | 16 | /** 17 | * Gets all NPC types. 18 | * @return all of the npc types 19 | */ 20 | Collection getAll(); 21 | } 22 | -------------------------------------------------------------------------------- /api/src/main/java/lol/pyr/znpcsplus/api/serialization/NpcSerializer.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.api.serialization; 2 | 3 | import lol.pyr.znpcsplus.api.npc.NpcEntry; 4 | 5 | public interface NpcSerializer { 6 | /** 7 | * Serialize an npc into the type of this serializer 8 | * @param entry The npc entry 9 | * @return The serialized class 10 | */ 11 | T serialize(NpcEntry entry); 12 | 13 | /** 14 | * Deserialize an npc from a serialized class 15 | * Note: This npc will not be registered, you need to also register it using the NpcRegistry#register(NpcEntry) method 16 | * @param model The serialized class 17 | * @return The deserialized NpcEntry 18 | */ 19 | NpcEntry deserialize(T model); 20 | } 21 | -------------------------------------------------------------------------------- /api/src/main/java/lol/pyr/znpcsplus/api/serialization/NpcSerializerRegistry.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.api.serialization; 2 | 3 | public interface NpcSerializerRegistry { 4 | /** 5 | * Get an NpcSerializer that serializes npcs into the provided class 6 | * @param clazz The class to serialize into 7 | * @return The npc serializer instance 8 | * @param The type of the class that the serializer serializes into 9 | */ 10 | NpcSerializer getSerializer(Class clazz); 11 | 12 | /** 13 | * Register an NpcSerializer to be used by other plugins 14 | * @param clazz The class that the serializer serializes into 15 | * @param serializer The serializer itself 16 | * @param The type of the class that the serializer serializes into 17 | */ 18 | void registerSerializer(Class clazz, NpcSerializer serializer); 19 | } 20 | -------------------------------------------------------------------------------- /api/src/main/java/lol/pyr/znpcsplus/api/skin/Skin.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.api.skin; 2 | 3 | public interface Skin { 4 | String getTexture(); 5 | String getSignature(); 6 | } 7 | -------------------------------------------------------------------------------- /api/src/main/java/lol/pyr/znpcsplus/api/skin/SkinDescriptor.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.api.skin; 2 | 3 | import org.bukkit.entity.Player; 4 | 5 | import java.util.concurrent.CompletableFuture; 6 | 7 | public interface SkinDescriptor { 8 | CompletableFuture fetch(Player player); 9 | Skin fetchInstant(Player player); 10 | boolean supportsInstant(Player player); 11 | } 12 | -------------------------------------------------------------------------------- /api/src/main/java/lol/pyr/znpcsplus/api/skin/SkinDescriptorFactory.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.api.skin; 2 | 3 | import java.net.URL; 4 | import java.util.UUID; 5 | 6 | /** 7 | * Factory for creating skin descriptors. 8 | */ 9 | public interface SkinDescriptorFactory { 10 | SkinDescriptor createMirrorDescriptor(); 11 | SkinDescriptor createRefreshingDescriptor(String playerName); 12 | SkinDescriptor createRefreshingDescriptor(UUID playerUUID); 13 | SkinDescriptor createStaticDescriptor(String playerName); 14 | SkinDescriptor createStaticDescriptor(String texture, String signature); 15 | SkinDescriptor createUrlDescriptor(String url, String variant); 16 | SkinDescriptor createUrlDescriptor(URL url, String variant); 17 | SkinDescriptor createFileDescriptor(String path); 18 | } 19 | -------------------------------------------------------------------------------- /api/src/main/java/lol/pyr/znpcsplus/util/ArmadilloState.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.util; 2 | 3 | public enum ArmadilloState { 4 | IDLE, 5 | ROLLING, 6 | SCARED, 7 | UNROLLING 8 | } 9 | -------------------------------------------------------------------------------- /api/src/main/java/lol/pyr/znpcsplus/util/AttachDirection.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.util; 2 | 3 | public enum AttachDirection { 4 | DOWN, 5 | UP, 6 | NORTH, 7 | SOUTH, 8 | WEST, 9 | EAST 10 | } 11 | -------------------------------------------------------------------------------- /api/src/main/java/lol/pyr/znpcsplus/util/AxolotlVariant.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.util; 2 | 3 | public enum AxolotlVariant { 4 | LUCY, 5 | WILD, 6 | GOLD, 7 | CYAN, 8 | BLUE 9 | } 10 | -------------------------------------------------------------------------------- /api/src/main/java/lol/pyr/znpcsplus/util/BlockState.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.util; 2 | 3 | public class BlockState { 4 | private final int globalId; 5 | 6 | public BlockState(int globalId) { 7 | this.globalId = globalId; 8 | } 9 | 10 | public int getGlobalId() { 11 | return globalId; 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /api/src/main/java/lol/pyr/znpcsplus/util/CatVariant.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.util; 2 | 3 | public enum CatVariant { 4 | TABBY, 5 | BLACK, 6 | RED, 7 | SIAMESE, 8 | BRITISH_SHORTHAIR, 9 | CALICO, 10 | PERSIAN, 11 | RAGDOLL, 12 | WHITE, 13 | JELLIE, 14 | ALL_BLACK 15 | } 16 | -------------------------------------------------------------------------------- /api/src/main/java/lol/pyr/znpcsplus/util/CreeperState.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.util; 2 | 3 | public enum CreeperState { 4 | IDLE(-1), 5 | FUSE(1); 6 | 7 | private final int state; 8 | 9 | CreeperState(int state) { 10 | this.state = state; 11 | } 12 | 13 | public int getState() { 14 | return state; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /api/src/main/java/lol/pyr/znpcsplus/util/FoxVariant.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.util; 2 | 3 | public enum FoxVariant { 4 | RED, 5 | SNOW 6 | } 7 | -------------------------------------------------------------------------------- /api/src/main/java/lol/pyr/znpcsplus/util/FrogVariant.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.util; 2 | 3 | public enum FrogVariant { 4 | TEMPERATE, 5 | WARM, 6 | COLD 7 | } 8 | -------------------------------------------------------------------------------- /api/src/main/java/lol/pyr/znpcsplus/util/HorseArmor.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.util; 2 | 3 | public enum HorseArmor { 4 | NONE, 5 | IRON, 6 | GOLD, 7 | DIAMOND 8 | } 9 | -------------------------------------------------------------------------------- /api/src/main/java/lol/pyr/znpcsplus/util/HorseColor.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.util; 2 | 3 | public enum HorseColor { 4 | WHITE, 5 | CREAMY, 6 | CHESTNUT, 7 | BROWN, 8 | BLACK, 9 | GRAY, 10 | DARK_BROWN 11 | } 12 | -------------------------------------------------------------------------------- /api/src/main/java/lol/pyr/znpcsplus/util/HorseStyle.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.util; 2 | 3 | public enum HorseStyle { 4 | NONE, 5 | WHITE, 6 | WHITEFIELD, 7 | WHITE_DOTS, 8 | BLACK_DOTS 9 | } 10 | -------------------------------------------------------------------------------- /api/src/main/java/lol/pyr/znpcsplus/util/HorseType.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.util; 2 | 3 | public enum HorseType { 4 | HORSE, 5 | DONKEY, 6 | MULE, 7 | ZOMBIE, 8 | SKELETON 9 | } 10 | -------------------------------------------------------------------------------- /api/src/main/java/lol/pyr/znpcsplus/util/LlamaVariant.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.util; 2 | 3 | public enum LlamaVariant { 4 | CREAMY, 5 | WHITE, 6 | BROWN, 7 | GRAY 8 | } 9 | -------------------------------------------------------------------------------- /api/src/main/java/lol/pyr/znpcsplus/util/LookType.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.util; 2 | 3 | public enum LookType { 4 | FIXED, 5 | CLOSEST_PLAYER, 6 | PER_PLAYER 7 | } 8 | -------------------------------------------------------------------------------- /api/src/main/java/lol/pyr/znpcsplus/util/MooshroomVariant.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.util; 2 | 3 | public enum MooshroomVariant { 4 | RED, 5 | BROWN; 6 | 7 | public static String getVariantName(MooshroomVariant variant) { 8 | return variant.name().toLowerCase(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /api/src/main/java/lol/pyr/znpcsplus/util/NamedColor.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.util; 2 | 3 | public enum NamedColor { 4 | BLACK, 5 | DARK_BLUE, 6 | DARK_GREEN, 7 | DARK_AQUA, 8 | DARK_RED, 9 | DARK_PURPLE, 10 | GOLD, 11 | GRAY, 12 | DARK_GRAY, 13 | BLUE, 14 | GREEN, 15 | AQUA, 16 | RED, 17 | LIGHT_PURPLE, 18 | YELLOW, 19 | WHITE 20 | } 21 | -------------------------------------------------------------------------------- /api/src/main/java/lol/pyr/znpcsplus/util/NpcPose.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.util; 2 | 3 | // TODO: Seperate this out into multiple classes and multiple properties depending on the npc type 4 | // TODO: For example USING_TONGUE is only for the frog type but its usable everywhere 5 | 6 | // TODO #2: Add some backwards compatibility to some of these, like for example CROUCHING can be done 7 | // TODO #2: on older versions using the general Entity number 0 bitmask 8 | public enum NpcPose { 9 | STANDING, 10 | FALL_FLYING, 11 | SLEEPING, 12 | SWIMMING, 13 | SPIN_ATTACK, 14 | CROUCHING, 15 | LONG_JUMPING, 16 | DYING, 17 | CROAKING, 18 | USING_TONGUE, 19 | SITTING, 20 | ROARING, 21 | SNIFFING, 22 | EMERGING, 23 | DIGGING, 24 | SLIDING, 25 | SHOOTING, 26 | INHALING, 27 | } 28 | -------------------------------------------------------------------------------- /api/src/main/java/lol/pyr/znpcsplus/util/OcelotType.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.util; 2 | 3 | public enum OcelotType { 4 | OCELOT, 5 | TUXEDO, 6 | TABBY, 7 | SIAMESE, 8 | } 9 | -------------------------------------------------------------------------------- /api/src/main/java/lol/pyr/znpcsplus/util/PandaGene.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.util; 2 | 3 | public enum PandaGene { 4 | NORMAL, 5 | LAZY, 6 | WORRIED, 7 | PLAYFUL, 8 | BROWN, 9 | WEAK, 10 | AGGRESSIVE 11 | } 12 | -------------------------------------------------------------------------------- /api/src/main/java/lol/pyr/znpcsplus/util/ParrotVariant.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.util; 2 | 3 | public enum ParrotVariant { 4 | RED_BLUE, 5 | BLUE, 6 | GREEN, 7 | YELLOW_BLUE, 8 | GRAY 9 | } 10 | -------------------------------------------------------------------------------- /api/src/main/java/lol/pyr/znpcsplus/util/PuffState.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.util; 2 | 3 | public enum PuffState { 4 | DEFLATED, 5 | HALF_INFLATED, 6 | FULLY_INFLATED, 7 | } 8 | -------------------------------------------------------------------------------- /api/src/main/java/lol/pyr/znpcsplus/util/RabbitType.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.util; 2 | 3 | public enum RabbitType { 4 | BROWN(0), 5 | WHITE(1), 6 | BLACK(2), 7 | BLACK_AND_WHITE(3), 8 | GOLD(4), 9 | SALT_AND_PEPPER(5), 10 | THE_KILLER_BUNNY(99), 11 | TOAST(100); 12 | 13 | private final int id; 14 | 15 | RabbitType(int id) { 16 | this.id = id; 17 | } 18 | 19 | public int getId() { 20 | return id; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /api/src/main/java/lol/pyr/znpcsplus/util/SkeletonType.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.util; 2 | 3 | public enum SkeletonType { 4 | NORMAL, 5 | WITHER, 6 | STRAY; 7 | 8 | public byte getLegacyId() { 9 | return (byte) ordinal(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /api/src/main/java/lol/pyr/znpcsplus/util/SnifferState.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.util; 2 | 3 | public enum SnifferState { 4 | IDLING, 5 | FEELING_HAPPY, 6 | SCENTING, 7 | SNIFFING, 8 | SEARCHING, 9 | DIGGING, 10 | RISING 11 | } 12 | -------------------------------------------------------------------------------- /api/src/main/java/lol/pyr/znpcsplus/util/SpellType.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.util; 2 | 3 | public enum SpellType { 4 | NONE, 5 | SUMMON_VEX, 6 | ATTACK, 7 | WOLOLO, 8 | DISAPPEAR, 9 | BLINDNESS, 10 | } 11 | -------------------------------------------------------------------------------- /api/src/main/java/lol/pyr/znpcsplus/util/Vector3f.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.util; 2 | 3 | public class Vector3f { 4 | private final float x; 5 | private final float y; 6 | private final float z; 7 | 8 | public Vector3f() { 9 | this.x = 0.0F; 10 | this.y = 0.0F; 11 | this.z = 0.0F; 12 | } 13 | 14 | public Vector3f(float x, float y, float z) { 15 | this.x = x; 16 | this.y = y; 17 | this.z = z; 18 | } 19 | 20 | public Vector3f(String s) { 21 | String[] split = s.split(","); 22 | this.x = Float.parseFloat(split[0]); 23 | this.y = Float.parseFloat(split[1]); 24 | this.z = Float.parseFloat(split[2]); 25 | } 26 | 27 | public float getX() { 28 | return this.x; 29 | } 30 | 31 | public float getY() { 32 | return this.y; 33 | } 34 | 35 | public float getZ() { 36 | return this.z; 37 | } 38 | 39 | public String toString() { 40 | return this.x + "," + this.y + "," + this.z; 41 | } 42 | 43 | public static Vector3f zero() { 44 | return new Vector3f(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /api/src/main/java/lol/pyr/znpcsplus/util/Vector3i.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.util; 2 | 3 | public class Vector3i { 4 | private final int x; 5 | private final int y; 6 | private final int z; 7 | 8 | public Vector3i(int x, int y, int z) { 9 | this.x = x; 10 | this.y = y; 11 | this.z = z; 12 | } 13 | 14 | public int getX() { 15 | return this.x; 16 | } 17 | 18 | public int getY() { 19 | return this.y; 20 | } 21 | 22 | public int getZ() { 23 | return this.z; 24 | } 25 | 26 | public String toString() { 27 | return this.x + "," + this.y + "," + this.z; 28 | } 29 | 30 | public String toPrettyString() { 31 | return "(" + this.x + ", " + this.y + ", " + this.z + ")"; 32 | } 33 | 34 | public static Vector3i fromString(String s) { 35 | String[] split = s.split(","); 36 | if (split.length < 3) { 37 | return null; 38 | } else { 39 | try { 40 | return new Vector3i(Integer.parseInt(split[0]), Integer.parseInt(split[1]), Integer.parseInt(split[2])); 41 | } catch (NumberFormatException var3) { 42 | return null; 43 | } 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /api/src/main/java/lol/pyr/znpcsplus/util/VillagerLevel.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.util; 2 | 3 | public enum VillagerLevel { 4 | STONE, 5 | IRON, 6 | GOLD, 7 | EMERALD, 8 | DIAMOND 9 | } 10 | -------------------------------------------------------------------------------- /api/src/main/java/lol/pyr/znpcsplus/util/VillagerProfession.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.util; 2 | 3 | public enum VillagerProfession { 4 | NONE(0, 0), 5 | ARMORER(1, 3), 6 | BUTCHER(2, 4), 7 | CARTOGRAPHER(3, 1), 8 | CLERIC(4, 2), 9 | FARMER(5, 0), 10 | FISHERMAN(6, 0), 11 | FLETCHER(7, 0), 12 | LEATHER_WORKER(8, 4), 13 | LIBRARIAN(9, 1), 14 | MASON(10), 15 | NITWIT(11, 5), 16 | SHEPHERD(12, 0), 17 | TOOL_SMITH(13, 3), 18 | WEAPON_SMITH(14, 3); 19 | 20 | private final int id; 21 | private final int legacyId; 22 | 23 | VillagerProfession(int id) { 24 | this.id = id; 25 | this.legacyId = 0; 26 | } 27 | 28 | VillagerProfession(int id, int legacyId) { 29 | this.id = id; 30 | this.legacyId = legacyId; 31 | } 32 | 33 | public int getId() { 34 | return id; 35 | } 36 | 37 | public int getLegacyId() { 38 | return legacyId; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /api/src/main/java/lol/pyr/znpcsplus/util/VillagerType.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.util; 2 | 3 | public enum VillagerType { 4 | DESERT(0), 5 | JUNGLE(1), 6 | PLAINS(2), 7 | SAVANNA(3), 8 | SNOW(4), 9 | SWAMP(5), 10 | TAIGA(6); 11 | private final int id; 12 | 13 | VillagerType(int id) { 14 | this.id = id; 15 | } 16 | 17 | public int getId() { 18 | return id; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /api/src/main/java/lol/pyr/znpcsplus/util/WoldVariant.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.util; 2 | 3 | public enum WoldVariant { 4 | PALE(3), 5 | SPOTTED(6), 6 | SNOWY(5), 7 | BLACK(1), 8 | ASHEN(0), 9 | RUSTY(4), 10 | WOODS(8), 11 | CHESTNUT(2), 12 | STRIPED(7); 13 | 14 | private final int id; 15 | 16 | WoldVariant(int id) { 17 | this.id = id; 18 | } 19 | 20 | public int getId() { 21 | return id; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /api/src/main/java/lol/pyr/znpcsplus/util/ZombieType.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.util; 2 | 3 | public enum ZombieType { 4 | ZOMBIE, 5 | FARMER, 6 | LIBRARIAN, 7 | PRIEST, 8 | BLACKSMITH, 9 | BUTCHER, 10 | HUSK 11 | } 12 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | subprojects { 2 | apply plugin: "java" 3 | 4 | group "lol.pyr" 5 | version "2.1.0" + (System.getenv().containsKey("BUILD_ID") ? "-SNAPSHOT" : "") 6 | 7 | java { 8 | toolchain.languageVersion.set(JavaLanguageVersion.of(8)) 9 | } 10 | 11 | dependencies { 12 | compileOnly "org.jetbrains:annotations:26.0.1" 13 | compileOnly "org.spigotmc:spigot-api:1.8.8-R0.1-SNAPSHOT" 14 | } 15 | 16 | repositories { 17 | mavenCentral() 18 | maven { 19 | url "https://hub.spigotmc.org/nexus/content/repositories/snapshots/" 20 | } 21 | maven { 22 | url "https://repo.codemc.io/repository/maven-releases/" 23 | } 24 | maven { 25 | url "https://libraries.minecraft.net" 26 | } 27 | maven { 28 | url "https://repo.papermc.io/repository/maven-public/" 29 | } 30 | maven { 31 | url "https://repo.extendedclip.com/content/repositories/placeholderapi/" 32 | } 33 | maven { 34 | url "https://repo.pyr.lol/releases" 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pyrbu/ZNPCsPlus/63db907d325730e73367de4ce17133df2697ba76/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.2-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/commands/CenterCommand.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.commands; 2 | 3 | import lol.pyr.director.adventure.command.CommandContext; 4 | import lol.pyr.director.adventure.command.CommandHandler; 5 | import lol.pyr.director.common.command.CommandExecutionException; 6 | import lol.pyr.znpcsplus.npc.NpcEntryImpl; 7 | import lol.pyr.znpcsplus.npc.NpcImpl; 8 | import lol.pyr.znpcsplus.npc.NpcRegistryImpl; 9 | import net.kyori.adventure.text.Component; 10 | import net.kyori.adventure.text.format.NamedTextColor; 11 | 12 | import java.util.Collections; 13 | import java.util.List; 14 | 15 | public class CenterCommand implements CommandHandler { 16 | private final NpcRegistryImpl npcRegistry; 17 | 18 | public CenterCommand(NpcRegistryImpl npcRegistry) { 19 | this.npcRegistry = npcRegistry; 20 | } 21 | 22 | @Override 23 | public void run(CommandContext context) throws CommandExecutionException { 24 | context.setUsage(context.getLabel() + " center "); 25 | NpcImpl npc = context.parse(NpcEntryImpl.class).getNpc(); 26 | npc.setLocation(npc.getLocation().centered()); 27 | context.send(Component.text("NPC has been centered on it's current block.", NamedTextColor.GREEN)); 28 | } 29 | 30 | @Override 31 | public List suggest(CommandContext context) throws CommandExecutionException { 32 | if (context.argSize() == 1) return context.suggestCollection(npcRegistry.getModifiableIds()); 33 | return Collections.emptyList(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/commands/ChangeIdCommand.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.commands; 2 | 3 | import lol.pyr.director.adventure.command.CommandContext; 4 | import lol.pyr.director.adventure.command.CommandHandler; 5 | import lol.pyr.director.common.command.CommandExecutionException; 6 | import lol.pyr.znpcsplus.npc.NpcEntryImpl; 7 | import lol.pyr.znpcsplus.npc.NpcRegistryImpl; 8 | import net.kyori.adventure.text.Component; 9 | import net.kyori.adventure.text.format.NamedTextColor; 10 | 11 | import java.util.Collections; 12 | import java.util.List; 13 | 14 | public class ChangeIdCommand implements CommandHandler { 15 | private final NpcRegistryImpl npcRegistry; 16 | 17 | public ChangeIdCommand(NpcRegistryImpl npcRegistry) { 18 | this.npcRegistry = npcRegistry; 19 | } 20 | 21 | @Override 22 | public void run(CommandContext context) throws CommandExecutionException { 23 | context.setUsage(context.getLabel() + " changeid "); 24 | NpcEntryImpl old = context.parse(NpcEntryImpl.class); 25 | String newId = context.popString(); 26 | if (npcRegistry.getById(newId) != null) context.halt(Component.text("There is already an npc with the new id you have provided", NamedTextColor.RED)); 27 | npcRegistry.switchIds(old.getId(), newId); 28 | context.send(Component.text("Npc's id changed to " + newId.toLowerCase(), NamedTextColor.GREEN)); 29 | } 30 | 31 | @Override 32 | public List suggest(CommandContext context) throws CommandExecutionException { 33 | if (context.argSize() == 1) return context.suggestCollection(npcRegistry.getModifiableIds()); 34 | return Collections.emptyList(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/commands/CloneCommand.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.commands; 2 | 3 | import lol.pyr.director.adventure.command.CommandContext; 4 | import lol.pyr.director.adventure.command.CommandHandler; 5 | import lol.pyr.director.common.command.CommandExecutionException; 6 | import lol.pyr.znpcsplus.npc.NpcEntryImpl; 7 | import lol.pyr.znpcsplus.npc.NpcRegistryImpl; 8 | import lol.pyr.znpcsplus.npc.NpcTypeRegistryImpl; 9 | import lol.pyr.znpcsplus.util.NpcLocation; 10 | import net.kyori.adventure.text.Component; 11 | import net.kyori.adventure.text.format.NamedTextColor; 12 | import org.bukkit.entity.Player; 13 | 14 | import java.util.Collections; 15 | import java.util.List; 16 | 17 | public class CloneCommand implements CommandHandler { 18 | private final NpcRegistryImpl npcRegistry; 19 | 20 | public CloneCommand(NpcRegistryImpl npcRegistry) { 21 | this.npcRegistry = npcRegistry; 22 | } 23 | 24 | @Override 25 | public void run(CommandContext context) throws CommandExecutionException { 26 | context.setUsage(context.getLabel() + " clone "); 27 | Player player = context.ensureSenderIsPlayer(); 28 | 29 | String id = context.popString(); 30 | if (npcRegistry.getById(id) == null) context.halt(Component.text("NPC with ID " + id + " does not exist.", NamedTextColor.RED)); 31 | String newId = context.popString(); 32 | if (npcRegistry.getById(newId) != null) context.halt(Component.text("NPC with ID " + newId + " already exists.", NamedTextColor.RED)); 33 | 34 | npcRegistry.clone(id, newId, player.getWorld(), new NpcLocation(player.getLocation())); 35 | 36 | context.send(Component.text("Cloned NPC with ID " + id + " to ID " + newId + ".", NamedTextColor.GREEN)); 37 | } 38 | 39 | @Override 40 | public List suggest(CommandContext context) throws CommandExecutionException { 41 | if (context.argSize() == 1) return context.suggestCollection(npcRegistry.getModifiableIds()); 42 | return Collections.emptyList(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/commands/DeleteCommand.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.commands; 2 | 3 | import lol.pyr.director.adventure.command.CommandContext; 4 | import lol.pyr.director.adventure.command.CommandHandler; 5 | import lol.pyr.director.common.command.CommandExecutionException; 6 | import lol.pyr.znpcsplus.npc.NpcEntryImpl; 7 | import lol.pyr.znpcsplus.npc.NpcRegistryImpl; 8 | import net.kyori.adventure.platform.bukkit.BukkitAudiences; 9 | import net.kyori.adventure.text.Component; 10 | import net.kyori.adventure.text.format.NamedTextColor; 11 | 12 | import java.util.Collections; 13 | import java.util.List; 14 | 15 | public class DeleteCommand implements CommandHandler { 16 | private final NpcRegistryImpl npcRegistry; 17 | private final BukkitAudiences adventure; 18 | 19 | public DeleteCommand(NpcRegistryImpl npcRegistry, BukkitAudiences adventure) { 20 | this.npcRegistry = npcRegistry; 21 | this.adventure = adventure; 22 | } 23 | 24 | @Override 25 | public void run(CommandContext context) throws CommandExecutionException { 26 | context.setUsage(context.getLabel() + " delete "); 27 | NpcEntryImpl entry = context.parse(NpcEntryImpl.class); 28 | npcRegistry.delete(entry.getId()); 29 | adventure.sender(context.getSender()).sendMessage(Component.text("Deleted NPC with ID: " + entry.getId(), NamedTextColor.GREEN)); 30 | } 31 | 32 | @Override 33 | public List suggest(CommandContext context) throws CommandExecutionException { 34 | if (context.argSize() == 1) return context.suggestCollection(npcRegistry.getModifiableIds()); 35 | return Collections.emptyList(); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/commands/LookAtMeCommand.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.commands; 2 | 3 | import lol.pyr.director.adventure.command.CommandContext; 4 | import lol.pyr.director.adventure.command.CommandHandler; 5 | import lol.pyr.director.common.command.CommandExecutionException; 6 | import lol.pyr.znpcsplus.npc.NpcEntryImpl; 7 | import lol.pyr.znpcsplus.npc.NpcImpl; 8 | import lol.pyr.znpcsplus.npc.NpcRegistryImpl; 9 | import net.kyori.adventure.text.Component; 10 | import net.kyori.adventure.text.format.NamedTextColor; 11 | import org.bukkit.entity.Player; 12 | 13 | import java.util.Collections; 14 | import java.util.List; 15 | 16 | public class LookAtMeCommand implements CommandHandler { 17 | private final NpcRegistryImpl npcRegistry; 18 | 19 | public LookAtMeCommand(NpcRegistryImpl npcRegistry) { 20 | this.npcRegistry = npcRegistry; 21 | } 22 | 23 | @Override 24 | public void run(CommandContext context) throws CommandExecutionException { 25 | context.setUsage(context.getLabel() + " lookatme "); 26 | Player player = context.ensureSenderIsPlayer(); 27 | NpcImpl npc = context.parse(NpcEntryImpl.class).getNpc(); 28 | npc.setLocation(npc.getLocation().lookingAt(player.getLocation())); 29 | context.send(Component.text("NPC is now looking at you.", NamedTextColor.GREEN)); 30 | } 31 | 32 | @Override 33 | public List suggest(CommandContext context) throws CommandExecutionException { 34 | if (context.argSize() == 1) return context.suggestCollection(npcRegistry.getModifiableIds()); 35 | return Collections.emptyList(); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/commands/MoveCommand.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.commands; 2 | 3 | import lol.pyr.director.adventure.command.CommandContext; 4 | import lol.pyr.director.adventure.command.CommandHandler; 5 | import lol.pyr.director.common.command.CommandExecutionException; 6 | import lol.pyr.znpcsplus.npc.NpcEntryImpl; 7 | import lol.pyr.znpcsplus.npc.NpcImpl; 8 | import lol.pyr.znpcsplus.npc.NpcRegistryImpl; 9 | import lol.pyr.znpcsplus.util.NpcLocation; 10 | import net.kyori.adventure.text.Component; 11 | import net.kyori.adventure.text.format.NamedTextColor; 12 | import org.bukkit.entity.Player; 13 | 14 | import java.util.Collections; 15 | import java.util.List; 16 | import java.util.Objects; 17 | 18 | public class MoveCommand implements CommandHandler { 19 | private final NpcRegistryImpl npcRegistry; 20 | 21 | public MoveCommand(NpcRegistryImpl npcRegistry) { 22 | this.npcRegistry = npcRegistry; 23 | } 24 | 25 | @Override 26 | public void run(CommandContext context) throws CommandExecutionException { 27 | context.setUsage(context.getLabel() + " move "); 28 | Player player = context.ensureSenderIsPlayer(); 29 | NpcImpl npc = context.parse(NpcEntryImpl.class).getNpc(); 30 | npc.setLocation(new NpcLocation(player.getLocation())); 31 | if (!Objects.equals(npc.getWorld(), player.getWorld())) npc.setWorld(player.getWorld()); 32 | context.send(Component.text("NPC moved to your current location.", NamedTextColor.GREEN)); 33 | } 34 | 35 | @Override 36 | public List suggest(CommandContext context) throws CommandExecutionException { 37 | if (context.argSize() == 1) return context.suggestCollection(npcRegistry.getModifiableIds()); 38 | return Collections.emptyList(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/commands/ReloadConfigCommand.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.commands; 2 | 3 | import lol.pyr.director.adventure.command.CommandContext; 4 | import lol.pyr.director.adventure.command.CommandHandler; 5 | import lol.pyr.director.common.command.CommandExecutionException; 6 | import lol.pyr.znpcsplus.config.ConfigManager; 7 | import net.kyori.adventure.text.Component; 8 | import net.kyori.adventure.text.format.NamedTextColor; 9 | 10 | public class ReloadConfigCommand implements CommandHandler { 11 | private final ConfigManager configManager; 12 | 13 | public ReloadConfigCommand(ConfigManager configManager) { 14 | this.configManager = configManager; 15 | } 16 | 17 | @Override 18 | public void run(CommandContext context) throws CommandExecutionException { 19 | configManager.reload(); 20 | context.send(Component.text("Plugin configuration reloaded successfully", NamedTextColor.GREEN)); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/commands/TeleportCommand.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.commands; 2 | 3 | import lol.pyr.director.adventure.command.CommandContext; 4 | import lol.pyr.director.adventure.command.CommandHandler; 5 | import lol.pyr.director.common.command.CommandExecutionException; 6 | import lol.pyr.znpcsplus.npc.NpcEntryImpl; 7 | import lol.pyr.znpcsplus.npc.NpcImpl; 8 | import lol.pyr.znpcsplus.npc.NpcRegistryImpl; 9 | import lol.pyr.znpcsplus.util.FoliaUtil; 10 | import net.kyori.adventure.text.Component; 11 | import net.kyori.adventure.text.format.NamedTextColor; 12 | import org.bukkit.Location; 13 | import org.bukkit.entity.Player; 14 | 15 | import java.util.Collections; 16 | import java.util.List; 17 | 18 | public class TeleportCommand implements CommandHandler { 19 | private final NpcRegistryImpl npcRegistry; 20 | 21 | public TeleportCommand(NpcRegistryImpl npcRegistry) { 22 | this.npcRegistry = npcRegistry; 23 | } 24 | 25 | @Override 26 | public void run(CommandContext context) throws CommandExecutionException { 27 | context.setUsage(context.getLabel() + " teleport "); 28 | Player player = context.ensureSenderIsPlayer(); 29 | NpcImpl npc = context.parse(NpcEntryImpl.class).getNpc(); 30 | Location location = npc.getBukkitLocation(); 31 | if (location == null) context.halt("Unable to teleport to NPC, the world is not loaded!"); 32 | FoliaUtil.teleport(player, location); 33 | context.send(Component.text("Teleported to NPC!", NamedTextColor.GREEN)); 34 | } 35 | 36 | @Override 37 | public List suggest(CommandContext context) throws CommandExecutionException { 38 | if (context.argSize() == 1) return context.suggestCollection(npcRegistry.getModifiableIds()); 39 | return Collections.emptyList(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/commands/ToggleCommand.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.commands; 2 | 3 | import lol.pyr.director.adventure.command.CommandContext; 4 | import lol.pyr.director.adventure.command.CommandHandler; 5 | import lol.pyr.director.common.command.CommandExecutionException; 6 | import lol.pyr.znpcsplus.npc.NpcEntryImpl; 7 | import lol.pyr.znpcsplus.npc.NpcImpl; 8 | import lol.pyr.znpcsplus.npc.NpcRegistryImpl; 9 | import net.kyori.adventure.text.Component; 10 | import net.kyori.adventure.text.format.NamedTextColor; 11 | 12 | import java.util.Collections; 13 | import java.util.List; 14 | 15 | public class ToggleCommand implements CommandHandler { 16 | private final NpcRegistryImpl npcRegistry; 17 | 18 | public ToggleCommand(NpcRegistryImpl npcRegistry) { 19 | this.npcRegistry = npcRegistry; 20 | } 21 | 22 | @Override 23 | public void run(CommandContext context) throws CommandExecutionException { 24 | context.setUsage(context.getLabel() + " toggle []"); 25 | NpcImpl npc = context.parse(NpcEntryImpl.class).getNpc(); 26 | boolean enabled; 27 | if (context.argSize() == 1) { 28 | enabled = context.popString().equalsIgnoreCase("enable"); 29 | } else { 30 | enabled = !npc.isEnabled(); 31 | } 32 | npc.setEnabled(enabled); 33 | context.send(Component.text("NPC has been " + (enabled ? "enabled" : "disabled"), NamedTextColor.GREEN)); 34 | } 35 | 36 | @Override 37 | public List suggest(CommandContext context) throws CommandExecutionException { 38 | if (context.argSize() == 1) return context.suggestCollection(npcRegistry.getModifiableIds()); 39 | if (context.argSize() == 2) return context.suggestLiteral("enable", "disable"); 40 | return Collections.emptyList(); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/commands/TypeCommand.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.commands; 2 | 3 | import lol.pyr.director.adventure.command.CommandContext; 4 | import lol.pyr.director.adventure.command.CommandHandler; 5 | import lol.pyr.director.common.command.CommandExecutionException; 6 | import lol.pyr.znpcsplus.npc.*; 7 | import net.kyori.adventure.text.Component; 8 | import net.kyori.adventure.text.format.NamedTextColor; 9 | 10 | import java.util.Collections; 11 | import java.util.List; 12 | 13 | public class TypeCommand implements CommandHandler { 14 | private final NpcRegistryImpl registry; 15 | private final NpcTypeRegistryImpl typeRegistry; 16 | 17 | public TypeCommand(NpcRegistryImpl registry, NpcTypeRegistryImpl typeRegistry) { 18 | this.registry = registry; 19 | this.typeRegistry = typeRegistry; 20 | } 21 | 22 | @Override 23 | public void run(CommandContext context) throws CommandExecutionException { 24 | context.setUsage(context.getLabel() + " type "); 25 | NpcImpl npc = context.parse(NpcEntryImpl.class).getNpc(); 26 | NpcTypeImpl type = context.parse(NpcTypeImpl.class); 27 | npc.setType(type); 28 | context.send(Component.text("NPC type set to " + type.getName() + ".", NamedTextColor.GREEN)); 29 | } 30 | 31 | @Override 32 | public List suggest(CommandContext context) throws CommandExecutionException { 33 | if (context.argSize() == 1) return context.suggestCollection(registry.getModifiableIds()); 34 | if (context.argSize() == 2) return context.suggestStream(typeRegistry.getAllImpl().stream().map(NpcTypeImpl::getName)); 35 | return Collections.emptyList(); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/commands/action/ActionClearCommand.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.commands.action; 2 | 3 | import lol.pyr.director.adventure.command.CommandContext; 4 | import lol.pyr.director.adventure.command.CommandHandler; 5 | import lol.pyr.director.common.command.CommandExecutionException; 6 | import lol.pyr.znpcsplus.npc.NpcEntryImpl; 7 | import lol.pyr.znpcsplus.npc.NpcImpl; 8 | import lol.pyr.znpcsplus.npc.NpcRegistryImpl; 9 | import net.kyori.adventure.text.Component; 10 | import net.kyori.adventure.text.format.NamedTextColor; 11 | 12 | import java.util.Collections; 13 | import java.util.List; 14 | 15 | public class ActionClearCommand implements CommandHandler { 16 | private final NpcRegistryImpl npcRegistry; 17 | 18 | public ActionClearCommand(NpcRegistryImpl npcRegistry) { 19 | this.npcRegistry = npcRegistry; 20 | } 21 | 22 | @Override 23 | public void run(CommandContext context) throws CommandExecutionException { 24 | context.setUsage(context.getLabel() + " action clear "); 25 | NpcImpl npc = context.parse(NpcEntryImpl.class).getNpc(); 26 | if (npc.getActions().size() == 0) context.halt(Component.text("That npc doesn't have any actions", NamedTextColor.RED)); 27 | npc.clearActions(); 28 | context.send(Component.text("Removed all actions from the npc", NamedTextColor.GREEN)); 29 | } 30 | 31 | @Override 32 | public List suggest(CommandContext context) throws CommandExecutionException { 33 | if (context.argSize() == 1) return context.suggestCollection(npcRegistry.getModifiableIds()); 34 | return Collections.emptyList(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/commands/action/ActionDeleteCommand.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.commands.action; 2 | 3 | import lol.pyr.director.adventure.command.CommandContext; 4 | import lol.pyr.director.adventure.command.CommandHandler; 5 | import lol.pyr.director.common.command.CommandExecutionException; 6 | import lol.pyr.znpcsplus.npc.NpcEntryImpl; 7 | import lol.pyr.znpcsplus.npc.NpcImpl; 8 | import lol.pyr.znpcsplus.npc.NpcRegistryImpl; 9 | import net.kyori.adventure.text.Component; 10 | import net.kyori.adventure.text.format.NamedTextColor; 11 | 12 | import java.util.Collections; 13 | import java.util.List; 14 | import java.util.stream.Stream; 15 | 16 | public class ActionDeleteCommand implements CommandHandler { 17 | private final NpcRegistryImpl npcRegistry; 18 | 19 | public ActionDeleteCommand(NpcRegistryImpl npcRegistry) { 20 | this.npcRegistry = npcRegistry; 21 | } 22 | 23 | @Override 24 | public void run(CommandContext context) throws CommandExecutionException { 25 | context.setUsage(context.getLabel() + " action delete "); 26 | NpcImpl npc = context.parse(NpcEntryImpl.class).getNpc(); 27 | int index = context.parse(Integer.class); 28 | if (index >= npc.getActions().size() || index < 0) context.halt(Component.text("That npc doesn't have any action with the index " + index, NamedTextColor.RED)); 29 | npc.removeAction(index); 30 | context.send(Component.text("Removed action with index " + index, NamedTextColor.GREEN)); 31 | } 32 | 33 | @Override 34 | public List suggest(CommandContext context) throws CommandExecutionException { 35 | if (context.argSize() == 1) return context.suggestCollection(npcRegistry.getModifiableIds()); 36 | if (context.argSize() == 2) return context.suggestStream(Stream.iterate(0, n -> n + 1) 37 | .limit(context.suggestionParse(0, NpcEntryImpl.class).getNpc().getActions().size()) 38 | .map(String::valueOf)); 39 | return Collections.emptyList(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/commands/action/ActionListCommand.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.commands.action; 2 | 3 | import lol.pyr.director.adventure.command.CommandContext; 4 | import lol.pyr.director.adventure.command.CommandHandler; 5 | import lol.pyr.director.common.command.CommandExecutionException; 6 | import lol.pyr.znpcsplus.api.interaction.InteractionAction; 7 | import lol.pyr.znpcsplus.interaction.InteractionActionImpl; 8 | import lol.pyr.znpcsplus.npc.NpcEntryImpl; 9 | import lol.pyr.znpcsplus.npc.NpcRegistryImpl; 10 | 11 | import java.util.Collections; 12 | import java.util.List; 13 | 14 | public class ActionListCommand implements CommandHandler { 15 | private final NpcRegistryImpl npcRegistry; 16 | 17 | public ActionListCommand(NpcRegistryImpl npcRegistry) { 18 | this.npcRegistry = npcRegistry; 19 | } 20 | 21 | @Override 22 | public void run(CommandContext context) throws CommandExecutionException { 23 | context.setUsage(context.getLabel() + " action list "); 24 | NpcEntryImpl entry = context.parse(NpcEntryImpl.class); 25 | List actions = entry.getNpc().getActions(); 26 | context.send("Actions of Npc " + entry.getId() + ":"); 27 | for (int i = 0; i < actions.size(); i++) { 28 | if (actions.get(i) instanceof InteractionActionImpl) { 29 | context.send(((InteractionActionImpl) actions.get(i)).getInfo(entry.getId(), i, context)); 30 | } 31 | } 32 | } 33 | 34 | @Override 35 | public List suggest(CommandContext context) throws CommandExecutionException { 36 | if (context.argSize() == 1) return context.suggestCollection(npcRegistry.getModifiableIds()); 37 | return Collections.emptyList(); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/commands/hologram/HoloAddCommand.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.commands.hologram; 2 | 3 | import lol.pyr.director.adventure.command.CommandContext; 4 | import lol.pyr.director.adventure.command.CommandHandler; 5 | import lol.pyr.director.common.command.CommandExecutionException; 6 | import lol.pyr.znpcsplus.hologram.HologramImpl; 7 | import lol.pyr.znpcsplus.hologram.HologramItem; 8 | import lol.pyr.znpcsplus.npc.NpcEntryImpl; 9 | import lol.pyr.znpcsplus.npc.NpcRegistryImpl; 10 | import net.kyori.adventure.text.Component; 11 | import net.kyori.adventure.text.format.NamedTextColor; 12 | 13 | import java.util.Collections; 14 | import java.util.List; 15 | 16 | public class HoloAddCommand implements CommandHandler { 17 | private final NpcRegistryImpl registry; 18 | 19 | public HoloAddCommand(NpcRegistryImpl registry) { 20 | this.registry = registry; 21 | } 22 | 23 | @Override 24 | public void run(CommandContext context) throws CommandExecutionException { 25 | context.setUsage(context.getLabel() + " holo add "); 26 | HologramImpl hologram = context.parse(NpcEntryImpl.class).getNpc().getHologram(); 27 | context.ensureArgsNotEmpty(); 28 | String in = context.dumpAllArgs(); 29 | if (in.toLowerCase().startsWith("item:")) { 30 | if (!HologramItem.ensureValidItemInput(in.substring(5))) { 31 | context.halt(Component.text("The item input is invalid!", NamedTextColor.RED)); 32 | } 33 | } 34 | hologram.addLine(in); 35 | context.send(Component.text("NPC line added!", NamedTextColor.GREEN)); 36 | } 37 | 38 | @Override 39 | public List suggest(CommandContext context) throws CommandExecutionException { 40 | if (context.argSize() == 1) return context.suggestCollection(registry.getModifiableIds()); 41 | return Collections.emptyList(); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/commands/hologram/HoloAddItemCommand.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.commands.hologram; 2 | 3 | import lol.pyr.director.adventure.command.CommandContext; 4 | import lol.pyr.director.adventure.command.CommandHandler; 5 | import lol.pyr.director.common.command.CommandExecutionException; 6 | import lol.pyr.znpcsplus.hologram.HologramImpl; 7 | import lol.pyr.znpcsplus.npc.NpcEntryImpl; 8 | import lol.pyr.znpcsplus.npc.NpcRegistryImpl; 9 | import net.kyori.adventure.text.Component; 10 | import net.kyori.adventure.text.format.NamedTextColor; 11 | import org.bukkit.entity.Player; 12 | 13 | import java.util.Collections; 14 | import java.util.List; 15 | 16 | public class HoloAddItemCommand implements CommandHandler { 17 | private final NpcRegistryImpl registry; 18 | 19 | public HoloAddItemCommand(NpcRegistryImpl registry) { 20 | this.registry = registry; 21 | } 22 | 23 | @Override 24 | public void run(CommandContext context) throws CommandExecutionException { 25 | context.setUsage(context.getLabel() + " holo additem "); 26 | Player player = context.ensureSenderIsPlayer(); 27 | org.bukkit.inventory.ItemStack itemStack = player.getInventory().getItemInHand(); 28 | if (itemStack == null) context.halt(Component.text("You must be holding an item!", NamedTextColor.RED)); 29 | HologramImpl hologram = context.parse(NpcEntryImpl.class).getNpc().getHologram(); 30 | hologram.addItemLineStack(itemStack); 31 | context.send(Component.text("NPC item line added!", NamedTextColor.GREEN)); 32 | } 33 | 34 | @Override 35 | public List suggest(CommandContext context) throws CommandExecutionException { 36 | if (context.argSize() == 1) return context.suggestCollection(registry.getModifiableIds()); 37 | return Collections.emptyList(); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/commands/hologram/HoloDeleteCommand.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.commands.hologram; 2 | 3 | import lol.pyr.director.adventure.command.CommandContext; 4 | import lol.pyr.director.adventure.command.CommandHandler; 5 | import lol.pyr.director.common.command.CommandExecutionException; 6 | import lol.pyr.znpcsplus.hologram.HologramImpl; 7 | import lol.pyr.znpcsplus.npc.NpcEntryImpl; 8 | import lol.pyr.znpcsplus.npc.NpcRegistryImpl; 9 | import net.kyori.adventure.text.Component; 10 | import net.kyori.adventure.text.format.NamedTextColor; 11 | 12 | import java.util.Collections; 13 | import java.util.List; 14 | import java.util.stream.Stream; 15 | 16 | public class HoloDeleteCommand implements CommandHandler { 17 | private final NpcRegistryImpl npcRegistry; 18 | 19 | public HoloDeleteCommand(NpcRegistryImpl npcRegistry) { 20 | this.npcRegistry = npcRegistry; 21 | } 22 | 23 | @Override 24 | public void run(CommandContext context) throws CommandExecutionException { 25 | context.setUsage(context.getLabel() + " holo delete "); 26 | HologramImpl hologram = context.parse(NpcEntryImpl.class).getNpc().getHologram(); 27 | int line = context.parse(Integer.class); 28 | if (line < 0 || line >= hologram.getLines().size()) context.halt(Component.text("Invalid line number!", NamedTextColor.RED)); 29 | hologram.removeLine(line); 30 | context.send(Component.text("NPC line removed.", NamedTextColor.GREEN)); 31 | } 32 | 33 | @Override 34 | public List suggest(CommandContext context) throws CommandExecutionException { 35 | if (context.argSize() == 1) return context.suggestCollection(npcRegistry.getModifiableIds()); 36 | if (context.argSize() == 2) return context.suggestStream(Stream.iterate(0, n -> n + 1) 37 | .limit(context.suggestionParse(0, NpcEntryImpl.class).getNpc().getHologram().getLines().size()) 38 | .map(String::valueOf)); 39 | return Collections.emptyList(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/commands/hologram/HoloInfoCommand.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.commands.hologram; 2 | 3 | import lol.pyr.director.adventure.command.CommandContext; 4 | import lol.pyr.director.adventure.command.CommandHandler; 5 | import lol.pyr.director.common.command.CommandExecutionException; 6 | import lol.pyr.znpcsplus.hologram.HologramImpl; 7 | import lol.pyr.znpcsplus.npc.NpcEntryImpl; 8 | import lol.pyr.znpcsplus.npc.NpcRegistryImpl; 9 | import net.kyori.adventure.text.Component; 10 | import net.kyori.adventure.text.format.NamedTextColor; 11 | 12 | import java.util.Collections; 13 | import java.util.List; 14 | 15 | public class HoloInfoCommand implements CommandHandler { 16 | private final NpcRegistryImpl npcRegistry; 17 | 18 | public HoloInfoCommand(NpcRegistryImpl npcRegistry) { 19 | this.npcRegistry = npcRegistry; 20 | } 21 | 22 | @Override 23 | public void run(CommandContext context) throws CommandExecutionException { 24 | context.setUsage(context.getLabel() + " holo info "); 25 | NpcEntryImpl entry = context.parse(NpcEntryImpl.class); 26 | HologramImpl hologram = entry.getNpc().getHologram(); 27 | Component component = Component.text("NPC Hologram Info of ID " + entry.getId() + ":", NamedTextColor.GREEN).appendNewline(); 28 | for (int i = 0; i < hologram.getLines().size(); i++) { 29 | component = component.append(Component.text(i + ") ", NamedTextColor.GREEN)) 30 | .append(Component.text(hologram.getLine(i), NamedTextColor.WHITE)) 31 | .appendNewline(); 32 | } 33 | context.send(component); 34 | } 35 | 36 | @Override 37 | public List suggest(CommandContext context) throws CommandExecutionException { 38 | if (context.argSize() == 1) return context.suggestCollection(npcRegistry.getModifiableIds()); 39 | return Collections.emptyList(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/commands/hologram/HoloOffsetCommand.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.commands.hologram; 2 | 3 | import lol.pyr.director.adventure.command.CommandContext; 4 | import lol.pyr.director.adventure.command.CommandHandler; 5 | import lol.pyr.director.common.command.CommandExecutionException; 6 | import lol.pyr.znpcsplus.hologram.HologramImpl; 7 | import lol.pyr.znpcsplus.npc.NpcEntryImpl; 8 | import lol.pyr.znpcsplus.npc.NpcRegistryImpl; 9 | 10 | import java.util.Collections; 11 | import java.util.List; 12 | 13 | public class HoloOffsetCommand implements CommandHandler { 14 | private final NpcRegistryImpl npcRegistry; 15 | 16 | public HoloOffsetCommand(NpcRegistryImpl npcRegistry) { 17 | this.npcRegistry = npcRegistry; 18 | } 19 | 20 | @Override 21 | public void run(CommandContext context) throws CommandExecutionException { 22 | context.setUsage(context.getLabel() + " holo offset "); 23 | HologramImpl hologram = context.parse(NpcEntryImpl.class).getNpc().getHologram(); 24 | double offset = context.parse(Double.class); 25 | hologram.setOffset(offset); 26 | context.send("NPC hologram offset set!"); 27 | } 28 | 29 | @Override 30 | public List suggest(CommandContext context) throws CommandExecutionException { 31 | if (context.argSize() == 1) return context.suggestCollection(npcRegistry.getModifiableIds()); 32 | if (context.argSize() == 2) { 33 | HologramImpl hologram = context.suggestionParse(0, NpcEntryImpl.class).getNpc().getHologram(); 34 | return context.suggestLiteral(String.valueOf(hologram.getOffset())); 35 | } 36 | return Collections.emptyList(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/commands/hologram/HoloRefreshDelayCommand.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.commands.hologram; 2 | 3 | import lol.pyr.director.adventure.command.CommandContext; 4 | import lol.pyr.director.adventure.command.CommandHandler; 5 | import lol.pyr.director.common.command.CommandExecutionException; 6 | import lol.pyr.znpcsplus.hologram.HologramImpl; 7 | import lol.pyr.znpcsplus.npc.NpcEntryImpl; 8 | import lol.pyr.znpcsplus.npc.NpcRegistryImpl; 9 | 10 | import java.util.Collections; 11 | import java.util.List; 12 | 13 | public class HoloRefreshDelayCommand implements CommandHandler { 14 | private final NpcRegistryImpl npcRegistry; 15 | 16 | public HoloRefreshDelayCommand(NpcRegistryImpl npcRegistry) { 17 | this.npcRegistry = npcRegistry; 18 | } 19 | 20 | @Override 21 | public void run(CommandContext context) throws CommandExecutionException { 22 | context.setUsage(context.getLabel() + " holo refreshdelay "); 23 | HologramImpl hologram = context.parse(NpcEntryImpl.class).getNpc().getHologram(); 24 | double delay = context.parse(Double.class); 25 | hologram.setRefreshDelay((long) (delay * 1000)); 26 | context.send("NPC refresh delay set!"); 27 | } 28 | 29 | @Override 30 | public List suggest(CommandContext context) throws CommandExecutionException { 31 | if (context.argSize() == 1) return context.suggestCollection(npcRegistry.getModifiableIds()); 32 | if (context.argSize() == 2) { 33 | HologramImpl hologram = context.suggestionParse(0, NpcEntryImpl.class).getNpc().getHologram(); 34 | return context.suggestLiteral(String.valueOf(((double) hologram.getRefreshDelay()) / 1000)); 35 | } 36 | return Collections.emptyList(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/commands/storage/LoadAllCommand.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.commands.storage; 2 | 3 | import lol.pyr.director.adventure.command.CommandContext; 4 | import lol.pyr.director.adventure.command.CommandHandler; 5 | import lol.pyr.director.common.command.CommandExecutionException; 6 | import lol.pyr.znpcsplus.npc.NpcRegistryImpl; 7 | import lol.pyr.znpcsplus.util.FutureUtil; 8 | import net.kyori.adventure.text.Component; 9 | import net.kyori.adventure.text.format.NamedTextColor; 10 | 11 | import java.util.Collections; 12 | import java.util.List; 13 | 14 | public class LoadAllCommand implements CommandHandler { 15 | private final NpcRegistryImpl npcRegistry; 16 | 17 | public LoadAllCommand(NpcRegistryImpl npcRegistry) { 18 | this.npcRegistry = npcRegistry; 19 | } 20 | 21 | @Override 22 | public void run(CommandContext context) throws CommandExecutionException { 23 | FutureUtil.exceptionPrintingRunAsync(() -> { 24 | npcRegistry.reload(); 25 | context.send(Component.text("All NPCs have been re-loaded from storage", NamedTextColor.GREEN)); 26 | }); 27 | } 28 | 29 | @Override 30 | public List suggest(CommandContext context) throws CommandExecutionException { 31 | return Collections.emptyList(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/commands/storage/SaveAllCommand.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.commands.storage; 2 | 3 | import lol.pyr.director.adventure.command.CommandContext; 4 | import lol.pyr.director.adventure.command.CommandHandler; 5 | import lol.pyr.director.common.command.CommandExecutionException; 6 | import lol.pyr.znpcsplus.npc.NpcRegistryImpl; 7 | import lol.pyr.znpcsplus.util.FutureUtil; 8 | import net.kyori.adventure.text.Component; 9 | import net.kyori.adventure.text.format.NamedTextColor; 10 | 11 | import java.util.Collections; 12 | import java.util.List; 13 | 14 | public class SaveAllCommand implements CommandHandler { 15 | private final NpcRegistryImpl npcRegistry; 16 | 17 | public SaveAllCommand(NpcRegistryImpl npcRegistry) { 18 | this.npcRegistry = npcRegistry; 19 | } 20 | 21 | @Override 22 | public void run(CommandContext context) throws CommandExecutionException { 23 | FutureUtil.exceptionPrintingRunAsync(() -> { 24 | npcRegistry.save(); 25 | context.send(Component.text("All NPCs have been saved to storage", NamedTextColor.GREEN)); 26 | }); 27 | } 28 | 29 | @Override 30 | public List suggest(CommandContext context) throws CommandExecutionException { 31 | return Collections.emptyList(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/config/ComponentSerializer.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.config; 2 | 3 | import net.kyori.adventure.text.Component; 4 | import net.kyori.adventure.text.minimessage.MiniMessage; 5 | import space.arim.dazzleconf.error.BadValueException; 6 | import space.arim.dazzleconf.serialiser.Decomposer; 7 | import space.arim.dazzleconf.serialiser.FlexibleType; 8 | import space.arim.dazzleconf.serialiser.ValueSerialiser; 9 | 10 | public class ComponentSerializer implements ValueSerialiser { 11 | @Override 12 | public Class getTargetClass() { 13 | return Component.class; 14 | } 15 | 16 | @Override 17 | public Component deserialise(FlexibleType flexibleType) throws BadValueException { 18 | return MiniMessage.miniMessage().deserialize(flexibleType.getString()); 19 | } 20 | 21 | @Override 22 | public Object serialise(Component value, Decomposer decomposer) { 23 | return MiniMessage.miniMessage().serialize(value); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/config/DatabaseConfig.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.config; 2 | 3 | import space.arim.dazzleconf.annote.ConfComments; 4 | import space.arim.dazzleconf.annote.ConfDefault.*; 5 | import space.arim.dazzleconf.annote.ConfKey; 6 | 7 | public interface DatabaseConfig { 8 | @ConfKey("host") 9 | @ConfComments("The host of the database") 10 | @DefaultString("localhost") 11 | String host(); 12 | 13 | @ConfKey("port") 14 | @ConfComments("The port of the database") 15 | @DefaultInteger(3306) 16 | int port(); 17 | 18 | @ConfKey("username") 19 | @ConfComments("The username to use to connect to the database") 20 | @DefaultString("znpcsplus") 21 | String username(); 22 | 23 | @ConfKey("password") 24 | @ConfComments("The password to use to connect to the database") 25 | @DefaultString("password") 26 | String password(); 27 | 28 | @ConfKey("database-name") 29 | @ConfComments("The name of the database to use") 30 | @DefaultString("znpcsplus") 31 | String databaseName(); 32 | 33 | @ConfKey("use-ssl") 34 | @ConfComments("Should SSL be used when connecting to the database?") 35 | @DefaultBoolean(false) 36 | boolean useSSL(); 37 | 38 | default String createConnectionURL(String dbType) { 39 | if (dbType.equalsIgnoreCase("mysql")) { 40 | return "jdbc:mysql://" + host() + ":" + port() + "/" + databaseName() + "?useSSL=" + useSSL(); 41 | } else { 42 | throw new IllegalArgumentException("Unsupported database type: " + dbType); 43 | } 44 | } 45 | } 46 | 47 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/conversion/DataImporter.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.conversion; 2 | 3 | import lol.pyr.znpcsplus.npc.NpcEntryImpl; 4 | 5 | import java.util.Collection; 6 | 7 | public interface DataImporter { 8 | Collection importData(); 9 | boolean isValid(); 10 | } 11 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/conversion/citizens/model/CitizensTrait.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.conversion.citizens.model; 2 | 3 | import lol.pyr.znpcsplus.npc.NpcImpl; 4 | import org.jetbrains.annotations.NotNull; 5 | 6 | public abstract class CitizensTrait { 7 | private final String identifier; 8 | 9 | public CitizensTrait(String identifier) { 10 | this.identifier = identifier; 11 | } 12 | 13 | public String getIdentifier() { 14 | return identifier; 15 | } 16 | 17 | public abstract @NotNull NpcImpl apply(NpcImpl npc, Object value); 18 | 19 | } 20 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/conversion/citizens/model/CitizensTraitsRegistry.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.conversion.citizens.model; 2 | 3 | import lol.pyr.znpcsplus.api.entity.EntityPropertyRegistry; 4 | import lol.pyr.znpcsplus.conversion.citizens.model.traits.*; 5 | import lol.pyr.znpcsplus.scheduling.TaskScheduler; 6 | import lol.pyr.znpcsplus.skin.cache.MojangSkinCache; 7 | import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; 8 | 9 | import java.util.HashMap; 10 | 11 | public class CitizensTraitsRegistry { 12 | private final HashMap traitMap = new HashMap<>(); 13 | 14 | public CitizensTraitsRegistry(EntityPropertyRegistry propertyRegistry, MojangSkinCache skinCache, TaskScheduler taskScheduler, LegacyComponentSerializer textSerializer) { 15 | register(new LocationTrait()); 16 | register(new ProfessionTrait(propertyRegistry)); 17 | register(new VillagerTrait(propertyRegistry)); 18 | register(new SkinTrait(propertyRegistry)); 19 | register(new MirrorTrait(propertyRegistry, skinCache)); 20 | register(new SkinLayersTrait(propertyRegistry)); 21 | register(new LookTrait(propertyRegistry)); 22 | register(new CommandTrait(taskScheduler)); 23 | register(new HologramTrait(textSerializer)); 24 | register(new EquipmentTrait(propertyRegistry)); 25 | register(new SpawnedTrait()); 26 | } 27 | 28 | public CitizensTrait getByName(String name) { 29 | return traitMap.get(name); 30 | } 31 | 32 | public void register(CitizensTrait trait) { 33 | traitMap.put(trait.getIdentifier(), trait); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/conversion/citizens/model/SectionCitizensTrait.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.conversion.citizens.model; 2 | 3 | import lol.pyr.znpcsplus.npc.NpcImpl; 4 | import org.bukkit.configuration.ConfigurationSection; 5 | import org.jetbrains.annotations.NotNull; 6 | 7 | public abstract class SectionCitizensTrait extends CitizensTrait { 8 | public SectionCitizensTrait(String identifier) { 9 | super(identifier); 10 | } 11 | 12 | @Override 13 | public @NotNull NpcImpl apply(NpcImpl npc, Object value) { 14 | if (!(value instanceof ConfigurationSection)) return npc; 15 | return apply(npc, (ConfigurationSection) value); 16 | } 17 | 18 | public abstract @NotNull NpcImpl apply(NpcImpl npc, ConfigurationSection section); 19 | } 20 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/conversion/citizens/model/StringCitizensTrait.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.conversion.citizens.model; 2 | 3 | import lol.pyr.znpcsplus.npc.NpcImpl; 4 | import org.jetbrains.annotations.NotNull; 5 | 6 | public abstract class StringCitizensTrait extends CitizensTrait { 7 | public StringCitizensTrait(String identifier) { 8 | super(identifier); 9 | } 10 | 11 | @Override 12 | public @NotNull NpcImpl apply(NpcImpl npc, Object value) { 13 | if (!(value instanceof String)) return npc; 14 | return apply(npc, (String) value); 15 | } 16 | 17 | public abstract @NotNull NpcImpl apply(NpcImpl npc, String string); 18 | } 19 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/conversion/citizens/model/traits/HologramTrait.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.conversion.citizens.model.traits; 2 | 3 | import lol.pyr.znpcsplus.conversion.citizens.model.SectionCitizensTrait; 4 | import lol.pyr.znpcsplus.npc.NpcImpl; 5 | import net.kyori.adventure.text.Component; 6 | import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; 7 | import org.bukkit.configuration.ConfigurationSection; 8 | import org.jetbrains.annotations.NotNull; 9 | 10 | import java.util.ArrayList; 11 | import java.util.List; 12 | 13 | public class HologramTrait extends SectionCitizensTrait { 14 | private final LegacyComponentSerializer textSerializer; 15 | 16 | public HologramTrait(LegacyComponentSerializer textSerializer) { 17 | super("hologramtrait"); 18 | this.textSerializer = textSerializer; 19 | } 20 | 21 | @Override 22 | public @NotNull NpcImpl apply(NpcImpl npc, ConfigurationSection section) { 23 | ConfigurationSection linesSection = section.getConfigurationSection("lines"); 24 | if (linesSection != null) { 25 | List keys = new ArrayList<>(linesSection.getKeys(false)); 26 | for (int i = keys.size() - 1; i >= 0; i--) { 27 | String line = linesSection.isConfigurationSection(keys.get(i)) ? linesSection.getConfigurationSection(keys.get(i)).getString("text") : linesSection.getString(keys.get(i)); 28 | if (line != null) { 29 | Component component = textSerializer.deserialize(line); 30 | npc.getHologram().addTextLineComponent(component); 31 | } 32 | } 33 | } 34 | return npc; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/conversion/citizens/model/traits/LocationTrait.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.conversion.citizens.model.traits; 2 | 3 | import lol.pyr.znpcsplus.conversion.citizens.model.SectionCitizensTrait; 4 | import lol.pyr.znpcsplus.npc.NpcImpl; 5 | import lol.pyr.znpcsplus.util.NpcLocation; 6 | import org.bukkit.configuration.ConfigurationSection; 7 | import org.jetbrains.annotations.NotNull; 8 | 9 | public class LocationTrait extends SectionCitizensTrait { 10 | public LocationTrait() { 11 | super("location"); 12 | } 13 | 14 | @Override 15 | public @NotNull NpcImpl apply(NpcImpl npc, ConfigurationSection section) { 16 | double x = Double.parseDouble(section.getString("x")); 17 | double y = Double.parseDouble(section.getString("y")); 18 | double z = Double.parseDouble(section.getString("z")); 19 | float yaw = Float.parseFloat(section.getString("yaw")); 20 | float pitch = Float.parseFloat(section.getString("pitch")); 21 | NpcLocation location = new NpcLocation(x, y, z, yaw, pitch); 22 | npc.setLocation(location); 23 | return npc; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/conversion/citizens/model/traits/LookTrait.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.conversion.citizens.model.traits; 2 | 3 | import lol.pyr.znpcsplus.api.entity.EntityPropertyRegistry; 4 | import lol.pyr.znpcsplus.conversion.citizens.model.SectionCitizensTrait; 5 | import lol.pyr.znpcsplus.npc.NpcImpl; 6 | import lol.pyr.znpcsplus.util.LookType; 7 | import org.bukkit.configuration.ConfigurationSection; 8 | import org.jetbrains.annotations.NotNull; 9 | 10 | public class LookTrait extends SectionCitizensTrait { 11 | private final EntityPropertyRegistry registry; 12 | 13 | public LookTrait(EntityPropertyRegistry registry) { 14 | super("lookclose"); 15 | this.registry = registry; 16 | } 17 | 18 | @Override 19 | public @NotNull NpcImpl apply(NpcImpl npc, ConfigurationSection section) { 20 | if (section.getBoolean("enabled")) npc.setProperty(registry.getByName("look", LookType.class), LookType.CLOSEST_PLAYER); 21 | return npc; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/conversion/citizens/model/traits/MirrorTrait.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.conversion.citizens.model.traits; 2 | 3 | import lol.pyr.znpcsplus.api.entity.EntityPropertyRegistry; 4 | import lol.pyr.znpcsplus.api.skin.SkinDescriptor; 5 | import lol.pyr.znpcsplus.conversion.citizens.model.SectionCitizensTrait; 6 | import lol.pyr.znpcsplus.npc.NpcImpl; 7 | import lol.pyr.znpcsplus.skin.cache.MojangSkinCache; 8 | import lol.pyr.znpcsplus.skin.descriptor.MirrorDescriptor; 9 | import org.bukkit.configuration.ConfigurationSection; 10 | import org.jetbrains.annotations.NotNull; 11 | 12 | public class MirrorTrait extends SectionCitizensTrait { 13 | private final EntityPropertyRegistry registry; 14 | private final MojangSkinCache skinCache; 15 | 16 | public MirrorTrait(EntityPropertyRegistry registry, MojangSkinCache skinCache) { 17 | super("mirrortrait"); 18 | this.registry = registry; 19 | this.skinCache = skinCache; 20 | } 21 | 22 | @Override 23 | public @NotNull NpcImpl apply(NpcImpl npc, ConfigurationSection section) { 24 | if (section.getBoolean("enabled")) npc.setProperty(registry.getByName("skin", SkinDescriptor.class), new MirrorDescriptor(skinCache)); 25 | return npc; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/conversion/citizens/model/traits/ProfessionTrait.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.conversion.citizens.model.traits; 2 | 3 | import lol.pyr.znpcsplus.api.entity.EntityPropertyRegistry; 4 | import lol.pyr.znpcsplus.conversion.citizens.model.StringCitizensTrait; 5 | import lol.pyr.znpcsplus.npc.NpcImpl; 6 | import lol.pyr.znpcsplus.util.VillagerProfession; 7 | import org.jetbrains.annotations.NotNull; 8 | 9 | public class ProfessionTrait extends StringCitizensTrait { 10 | private final EntityPropertyRegistry registry; 11 | 12 | public ProfessionTrait(EntityPropertyRegistry registry) { 13 | super("profession"); 14 | this.registry = registry; 15 | } 16 | 17 | @Override 18 | public @NotNull NpcImpl apply(NpcImpl npc, String string) { 19 | VillagerProfession profession; 20 | try { 21 | profession = VillagerProfession.valueOf(string.toUpperCase()); 22 | } catch (IllegalArgumentException ignored) { 23 | profession = VillagerProfession.NONE; 24 | } 25 | npc.setProperty(registry.getByName("villager_profession", VillagerProfession.class), profession); 26 | return npc; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/conversion/citizens/model/traits/SkinLayersTrait.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.conversion.citizens.model.traits; 2 | 3 | import lol.pyr.znpcsplus.api.entity.EntityPropertyRegistry; 4 | import lol.pyr.znpcsplus.conversion.citizens.model.SectionCitizensTrait; 5 | import lol.pyr.znpcsplus.npc.NpcImpl; 6 | import org.bukkit.configuration.ConfigurationSection; 7 | import org.jetbrains.annotations.NotNull; 8 | 9 | import java.util.HashMap; 10 | import java.util.Map; 11 | 12 | public class SkinLayersTrait extends SectionCitizensTrait { 13 | private final EntityPropertyRegistry registry; 14 | private final Map skinLayers; 15 | 16 | public SkinLayersTrait(EntityPropertyRegistry registry) { 17 | super("skinlayers"); 18 | this.registry = registry; 19 | this.skinLayers = new HashMap<>(); 20 | this.skinLayers.put("cape", "skin_cape"); 21 | this.skinLayers.put("hat", "skin_hat"); 22 | this.skinLayers.put("jacket", "skin_jacket"); 23 | this.skinLayers.put("left_sleeve", "skin_left_sleeve"); 24 | this.skinLayers.put("left_pants", "skin_left_leg"); 25 | this.skinLayers.put("right_sleeve", "skin_right_sleeve"); 26 | this.skinLayers.put("right_pants", "skin_right_leg"); 27 | } 28 | 29 | @Override 30 | public @NotNull NpcImpl apply(NpcImpl npc, ConfigurationSection section) { 31 | for (Map.Entry entry : this.skinLayers.entrySet()) { 32 | String key = entry.getKey(); 33 | String property = entry.getValue(); 34 | if (section.contains(key)) npc.setProperty(registry.getByName(property, Boolean.class), section.getBoolean(key)); 35 | } 36 | return npc; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/conversion/citizens/model/traits/SkinTrait.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.conversion.citizens.model.traits; 2 | 3 | import lol.pyr.znpcsplus.api.entity.EntityPropertyRegistry; 4 | import lol.pyr.znpcsplus.api.skin.SkinDescriptor; 5 | import lol.pyr.znpcsplus.conversion.citizens.model.SectionCitizensTrait; 6 | import lol.pyr.znpcsplus.npc.NpcImpl; 7 | import lol.pyr.znpcsplus.skin.SkinImpl; 8 | import lol.pyr.znpcsplus.skin.descriptor.PrefetchedDescriptor; 9 | import org.bukkit.configuration.ConfigurationSection; 10 | import org.jetbrains.annotations.NotNull; 11 | 12 | public class SkinTrait extends SectionCitizensTrait { 13 | private final EntityPropertyRegistry registry; 14 | 15 | public SkinTrait(EntityPropertyRegistry registry) { 16 | super("skintrait"); 17 | this.registry = registry; 18 | } 19 | 20 | @Override 21 | public @NotNull NpcImpl apply(NpcImpl npc, ConfigurationSection section) { 22 | String texture = section.getString("textureRaw"); 23 | String signature = section.getString("signature"); 24 | if (texture != null && signature != null) npc.setProperty(registry.getByName("skin", SkinDescriptor.class), new PrefetchedDescriptor(new SkinImpl(texture, signature))); 25 | return npc; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/conversion/citizens/model/traits/SpawnedTrait.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.conversion.citizens.model.traits; 2 | 3 | import lol.pyr.znpcsplus.conversion.citizens.model.CitizensTrait; 4 | import lol.pyr.znpcsplus.npc.NpcImpl; 5 | import org.jetbrains.annotations.NotNull; 6 | 7 | public class SpawnedTrait extends CitizensTrait { 8 | 9 | public SpawnedTrait() { 10 | super("spawned"); 11 | } 12 | 13 | @Override 14 | public @NotNull NpcImpl apply(NpcImpl npc, Object value) { 15 | if (value != null) { 16 | npc.setEnabled((boolean) value); 17 | } 18 | return npc; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/conversion/citizens/model/traits/TypeTrait.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.conversion.citizens.model.traits; 2 | 3 | import lol.pyr.znpcsplus.api.npc.NpcTypeRegistry; 4 | import lol.pyr.znpcsplus.conversion.citizens.model.StringCitizensTrait; 5 | import lol.pyr.znpcsplus.npc.NpcImpl; 6 | import lol.pyr.znpcsplus.npc.NpcTypeImpl; 7 | import org.jetbrains.annotations.NotNull; 8 | 9 | public class TypeTrait extends StringCitizensTrait { 10 | private final NpcTypeRegistry registry; 11 | 12 | public TypeTrait(NpcTypeRegistry registry) { 13 | super("type"); 14 | this.registry = registry; 15 | } 16 | 17 | @Override 18 | public @NotNull NpcImpl apply(NpcImpl npc, String string) { 19 | NpcTypeImpl type = warpNpcType(string); 20 | if (type == null) return npc; 21 | npc.setType(type); 22 | return npc; 23 | } 24 | 25 | private NpcTypeImpl warpNpcType(String name) { 26 | name = name.toLowerCase(); 27 | // if (name.equals("player")) name = "human"; 28 | // else if (name.equals("zombievillager")) name = "zombie_villager"; 29 | return (NpcTypeImpl) registry.getByName(name); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/conversion/citizens/model/traits/VillagerTrait.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.conversion.citizens.model.traits; 2 | 3 | import lol.pyr.znpcsplus.api.entity.EntityPropertyRegistry; 4 | import lol.pyr.znpcsplus.conversion.citizens.model.SectionCitizensTrait; 5 | import lol.pyr.znpcsplus.npc.NpcImpl; 6 | import lol.pyr.znpcsplus.util.VillagerLevel; 7 | import lol.pyr.znpcsplus.util.VillagerType; 8 | import org.bukkit.configuration.ConfigurationSection; 9 | import org.jetbrains.annotations.NotNull; 10 | 11 | public class VillagerTrait extends SectionCitizensTrait { 12 | private final EntityPropertyRegistry registry; 13 | 14 | public VillagerTrait(EntityPropertyRegistry registry) { 15 | super("villagertrait"); 16 | this.registry = registry; 17 | } 18 | 19 | @Override 20 | public @NotNull NpcImpl apply(NpcImpl npc, ConfigurationSection section) { 21 | int level = section.getInt("level"); 22 | String type = section.getString("type", "plains"); 23 | VillagerLevel villagerLevel; 24 | try { 25 | villagerLevel = VillagerLevel.values()[level]; 26 | } catch (ArrayIndexOutOfBoundsException ignored) { 27 | villagerLevel = VillagerLevel.STONE; 28 | } 29 | VillagerType villagerType; 30 | try { 31 | villagerType = VillagerType.valueOf(type.toUpperCase()); 32 | } catch (IllegalArgumentException ignored) { 33 | villagerType = VillagerType.PLAINS; 34 | } 35 | npc.setProperty(registry.getByName("villager_level", VillagerLevel.class), villagerLevel); 36 | npc.setProperty(registry.getByName("villager_type", VillagerType.class), villagerType); 37 | return npc; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/conversion/znpcs/model/ZNpcsAction.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.conversion.znpcs.model; 2 | 3 | @SuppressWarnings("unused") 4 | public class ZNpcsAction { 5 | private String actionType; 6 | private String clickType; 7 | private String action; 8 | private int delay; 9 | 10 | public String getActionType() { 11 | return actionType; 12 | } 13 | 14 | public String getClickType() { 15 | return clickType; 16 | } 17 | 18 | public String getAction() { 19 | return action; 20 | } 21 | 22 | public int getDelay() { 23 | return delay; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/conversion/znpcs/model/ZNpcsConversation.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.conversion.znpcs.model; 2 | 3 | @SuppressWarnings("unused") 4 | public class ZNpcsConversation { 5 | 6 | private String conversationName; 7 | private String conversationType; 8 | 9 | public String getConversationName() { 10 | return conversationName; 11 | } 12 | 13 | public String getConversationType() { 14 | return conversationType; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/conversion/znpcs/model/ZNpcsConversationText.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.conversion.znpcs.model; 2 | 3 | @SuppressWarnings("unused") 4 | public class ZNpcsConversationText { 5 | 6 | private String[] lines; 7 | private ZNpcsAction[] actions; 8 | private int delay; 9 | 10 | public String[] getLines() { 11 | return lines; 12 | } 13 | public ZNpcsAction[] getActions() { 14 | return actions; 15 | } 16 | public int getDelay() { 17 | return delay; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/conversion/znpcs/model/ZNpcsLocation.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.conversion.znpcs.model; 2 | 3 | @SuppressWarnings("unused") 4 | public class ZNpcsLocation { 5 | private String world; 6 | private double x; 7 | private double y; 8 | private double z; 9 | private float yaw; 10 | private float pitch; 11 | 12 | public String getWorld() { 13 | return world; 14 | } 15 | 16 | public double getX() { 17 | return x; 18 | } 19 | 20 | public double getY() { 21 | return y; 22 | } 23 | 24 | public double getZ() { 25 | return z; 26 | } 27 | 28 | public float getYaw() { 29 | return yaw; 30 | } 31 | 32 | public float getPitch() { 33 | return pitch; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/conversion/znpcs/model/ZnpcsConversations.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.conversion.znpcs.model; 2 | 3 | @SuppressWarnings("unused") 4 | public class ZnpcsConversations { 5 | 6 | private String name; 7 | private ZNpcsConversationText[] texts; 8 | private int radius; 9 | private int delay; 10 | 11 | public String getName() { 12 | return name; 13 | } 14 | public ZNpcsConversationText[] getTexts() { 15 | return texts; 16 | } 17 | public int getRadius() { 18 | return radius; 19 | } 20 | public int getDelay() { 21 | return delay; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/entity/EnumPropertySerializer.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.entity; 2 | 3 | public class EnumPropertySerializer> implements PropertySerializer { 4 | 5 | private final Class enumClass; 6 | 7 | public EnumPropertySerializer(Class enumClass) { 8 | this.enumClass = enumClass; 9 | } 10 | 11 | @Override 12 | public String serialize(T property) { 13 | return property.name(); 14 | } 15 | 16 | @Override 17 | public T deserialize(String property) { 18 | try { 19 | return Enum.valueOf(enumClass, property.toUpperCase()); 20 | } catch (IllegalArgumentException e) { 21 | return null; 22 | } 23 | } 24 | 25 | @Override 26 | public Class getTypeClass() { 27 | return enumClass; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/entity/ParrotNBTCompound.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.entity; 2 | 3 | import com.github.retrooper.packetevents.protocol.nbt.NBTCompound; 4 | import com.github.retrooper.packetevents.protocol.nbt.NBTInt; 5 | import com.github.retrooper.packetevents.protocol.nbt.NBTString; 6 | import lol.pyr.znpcsplus.util.ParrotVariant; 7 | 8 | // Not sure where to put this or even if it's needed 9 | public class ParrotNBTCompound { 10 | private final NBTCompound tag = new NBTCompound(); 11 | 12 | public ParrotNBTCompound(ParrotVariant variant) { 13 | tag.setTag("id", new NBTString("minecraft:parrot")); 14 | tag.setTag("Variant", new NBTInt(variant.ordinal())); 15 | // other tags if needed, idk 16 | } 17 | 18 | public NBTCompound getTag() { 19 | return tag; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/entity/PrimitivePropertySerializer.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.entity; 2 | 3 | import java.lang.reflect.InvocationTargetException; 4 | 5 | public class PrimitivePropertySerializer implements PropertySerializer { 6 | private final Class clazz; 7 | 8 | public PrimitivePropertySerializer(Class clazz) { 9 | this.clazz = clazz; 10 | } 11 | 12 | @Override 13 | public String serialize(T property) { 14 | return String.valueOf(property); 15 | } 16 | 17 | @Override 18 | public T deserialize(String property) { 19 | try { 20 | return clazz.getConstructor(String.class).newInstance(property); 21 | } catch (InvocationTargetException | InstantiationException | IllegalAccessException | NoSuchMethodException e) { 22 | throw new NullPointerException("Failed to deserialize property " + property + " of type " + clazz.getName() + "!"); 23 | } 24 | } 25 | 26 | @Override 27 | public Class getTypeClass() { 28 | return clazz; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/entity/PropertySerializer.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.entity; 2 | 3 | public interface PropertySerializer { 4 | String serialize(T property); 5 | T deserialize(String property); 6 | Class getTypeClass(); 7 | 8 | @SuppressWarnings("unchecked") 9 | default String UNSAFE_serialize(Object property) { 10 | return serialize((T) property); 11 | } 12 | } -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/BooleanProperty.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.entity.properties; 2 | 3 | import com.github.retrooper.packetevents.protocol.entity.data.EntityData; 4 | import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes; 5 | import lol.pyr.znpcsplus.entity.EntityPropertyImpl; 6 | import lol.pyr.znpcsplus.entity.PacketEntity; 7 | import org.bukkit.entity.Player; 8 | 9 | import java.util.Map; 10 | 11 | public class BooleanProperty extends EntityPropertyImpl { 12 | private final int index; 13 | private final boolean legacy; 14 | private final boolean inverted; 15 | 16 | public BooleanProperty(String name, int index, boolean defaultValue, boolean legacy) { 17 | this(name, index, defaultValue, legacy, false); 18 | } 19 | 20 | public BooleanProperty(String name, int index, boolean defaultValue, boolean legacy, boolean inverted) { 21 | super(name, defaultValue, Boolean.class); 22 | this.index = index; 23 | this.legacy = legacy; 24 | this.inverted = inverted; 25 | } 26 | 27 | @Override 28 | public void apply(Player player, PacketEntity entity, boolean isSpawned, Map> properties) { 29 | boolean enabled = entity.getProperty(this); 30 | if (inverted) enabled = !enabled; 31 | if (legacy) properties.put(index, newEntityData(index, EntityDataTypes.BYTE, (byte) (enabled ? 1 : 0))); 32 | else properties.put(index, newEntityData(index, EntityDataTypes.BOOLEAN, enabled)); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/CamelSittingProperty.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.entity.properties; 2 | 3 | import com.github.retrooper.packetevents.protocol.entity.data.EntityData; 4 | import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes; 5 | import com.github.retrooper.packetevents.protocol.entity.pose.EntityPose; 6 | import lol.pyr.znpcsplus.entity.EntityPropertyImpl; 7 | import lol.pyr.znpcsplus.entity.PacketEntity; 8 | import org.bukkit.entity.Player; 9 | 10 | import java.util.Map; 11 | 12 | public class CamelSittingProperty extends EntityPropertyImpl { 13 | private final int poseIndex; 14 | private final int lastPoseTickIndex; 15 | 16 | public CamelSittingProperty(int poseIndex, int lastPoseTickIndex) { 17 | super("camel_sitting", false, Boolean.class); 18 | this.poseIndex = poseIndex; 19 | this.lastPoseTickIndex = lastPoseTickIndex; 20 | } 21 | 22 | @Override 23 | public void apply(Player player, PacketEntity entity, boolean isSpawned, Map> properties) { 24 | boolean value = entity.getProperty(this); 25 | if (value) { 26 | properties.put(poseIndex, newEntityData(poseIndex, EntityDataTypes.ENTITY_POSE, EntityPose.SITTING)); 27 | properties.put(lastPoseTickIndex, newEntityData(lastPoseTickIndex, EntityDataTypes.LONG, -1L)); 28 | } else { 29 | properties.put(poseIndex, newEntityData(poseIndex, EntityDataTypes.ENTITY_POSE, EntityPose.STANDING)); 30 | properties.put(lastPoseTickIndex, newEntityData(lastPoseTickIndex, EntityDataTypes.LONG, 0L)); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/CustomTypeProperty.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.entity.properties; 2 | 3 | import com.github.retrooper.packetevents.protocol.entity.data.EntityData; 4 | import com.github.retrooper.packetevents.protocol.entity.data.EntityDataType; 5 | import lol.pyr.znpcsplus.entity.EntityPropertyImpl; 6 | import lol.pyr.znpcsplus.entity.PacketEntity; 7 | import org.bukkit.entity.Player; 8 | 9 | import java.util.Map; 10 | 11 | public class CustomTypeProperty extends EntityPropertyImpl { 12 | private final int index; 13 | private final EntityDataType type; 14 | private final TypeDecoder decoder; 15 | 16 | @SuppressWarnings("unchecked") 17 | public CustomTypeProperty(String name, int index, T def, EntityDataType type, TypeDecoder decoder) { 18 | super(name, def, (Class) def.getClass()); 19 | this.index = index; 20 | this.type = type; 21 | this.decoder = decoder; 22 | } 23 | 24 | @Override 25 | public void apply(Player player, PacketEntity entity, boolean isSpawned, Map> properties) { 26 | properties.put(index, newEntityData(index, type, decoder.decode(entity.getProperty(this)))); 27 | } 28 | 29 | public interface TypeDecoder { 30 | U decode(T obj); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/DinnerboneProperty.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.entity.properties; 2 | 3 | import com.github.retrooper.packetevents.protocol.entity.data.EntityData; 4 | import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes; 5 | import com.github.retrooper.packetevents.util.adventure.AdventureSerializer; 6 | import lol.pyr.znpcsplus.entity.EntityPropertyImpl; 7 | import lol.pyr.znpcsplus.entity.PacketEntity; 8 | import net.kyori.adventure.text.Component; 9 | import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; 10 | import org.bukkit.entity.Player; 11 | 12 | import java.util.Map; 13 | import java.util.Optional; 14 | 15 | public class DinnerboneProperty extends EntityPropertyImpl { 16 | private final boolean optional; 17 | private final Object serialized; 18 | 19 | public DinnerboneProperty(boolean legacy, boolean optional) { 20 | super("dinnerbone", false, Boolean.class); 21 | this.optional = optional; 22 | Component name = Component.text("Dinnerbone"); 23 | this.serialized = legacy ? AdventureSerializer.serializer().legacy().serialize(name) : 24 | optional ? name : LegacyComponentSerializer.legacySection().serialize(name); 25 | } 26 | 27 | @Override 28 | public void apply(Player player, PacketEntity entity, boolean isSpawned, Map> properties) { 29 | if (optional) { 30 | properties.put(2, new EntityData<>(2, EntityDataTypes.OPTIONAL_ADV_COMPONENT, entity.getProperty(this) ? Optional.of((Component) serialized) : Optional.empty())); 31 | } else { 32 | properties.put(2, new EntityData<>(2, EntityDataTypes.STRING, entity.getProperty(this) ? (String) serialized : "")); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/DummyProperty.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.entity.properties; 2 | 3 | import com.github.retrooper.packetevents.protocol.entity.data.EntityData; 4 | import lol.pyr.znpcsplus.entity.EntityPropertyImpl; 5 | import lol.pyr.znpcsplus.entity.PacketEntity; 6 | import org.bukkit.entity.Player; 7 | 8 | import java.util.Map; 9 | 10 | public class DummyProperty extends EntityPropertyImpl { 11 | public DummyProperty(String name, T defaultValue) { 12 | this(name, defaultValue, true); 13 | } 14 | 15 | public DummyProperty(String name, Class clazz) { 16 | this(name, clazz, true); 17 | } 18 | 19 | @SuppressWarnings("unchecked") 20 | public DummyProperty(String name, T defaultValue, boolean playerModifiable) { 21 | super(name, defaultValue, (Class) defaultValue.getClass()); 22 | setPlayerModifiable(playerModifiable); 23 | } 24 | 25 | public DummyProperty(String name, Class clazz, boolean playerModifiable) { 26 | super(name, null, clazz); 27 | setPlayerModifiable(playerModifiable); 28 | } 29 | 30 | @Override 31 | public void apply(Player player, PacketEntity entity, boolean isSpawned, Map> properties) { 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/EntitySittingProperty.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.entity.properties; 2 | 3 | import com.github.retrooper.packetevents.protocol.entity.data.EntityData; 4 | import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes; 5 | import lol.pyr.znpcsplus.entity.ArmorStandVehicleProperties; 6 | import lol.pyr.znpcsplus.entity.EntityPropertyImpl; 7 | import lol.pyr.znpcsplus.entity.EntityPropertyRegistryImpl; 8 | import lol.pyr.znpcsplus.entity.PacketEntity; 9 | import lol.pyr.znpcsplus.packets.PacketFactory; 10 | import org.bukkit.entity.Player; 11 | 12 | import java.util.Map; 13 | 14 | public class EntitySittingProperty extends EntityPropertyImpl { 15 | private final PacketFactory packetFactory; 16 | private final EntityPropertyRegistryImpl propertyRegistry; 17 | 18 | public EntitySittingProperty(PacketFactory packetFactory, EntityPropertyRegistryImpl propertyRegistry) { 19 | super("entity_sitting", false, Boolean.class); 20 | this.packetFactory = packetFactory; 21 | this.propertyRegistry = propertyRegistry; 22 | } 23 | 24 | @Override 25 | public void apply(Player player, PacketEntity entity, boolean isSpawned, Map> properties) { 26 | boolean sitting = entity.getProperty(this); 27 | if (sitting) { 28 | if (entity.getVehicle() == null) { 29 | PacketEntity vehiclePacketEntity = new PacketEntity(packetFactory, new ArmorStandVehicleProperties(propertyRegistry), 30 | entity.getViewable(), EntityTypes.ARMOR_STAND, entity.getLocation().withY(entity.getLocation().getY() - 0.9)); 31 | entity.setVehicle(vehiclePacketEntity); 32 | } 33 | } else if (entity.getVehicle() != null) { 34 | entity.setVehicle(null); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/EquipmentProperty.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.entity.properties; 2 | 3 | import com.github.retrooper.packetevents.protocol.entity.data.EntityData; 4 | import com.github.retrooper.packetevents.protocol.item.ItemStack; 5 | import com.github.retrooper.packetevents.protocol.player.Equipment; 6 | import com.github.retrooper.packetevents.protocol.player.EquipmentSlot; 7 | import lol.pyr.znpcsplus.entity.EntityPropertyImpl; 8 | import lol.pyr.znpcsplus.entity.PacketEntity; 9 | import lol.pyr.znpcsplus.packets.PacketFactory; 10 | import org.bukkit.entity.Player; 11 | 12 | import java.util.Map; 13 | 14 | public class EquipmentProperty extends EntityPropertyImpl { 15 | private final PacketFactory packetFactory; 16 | private final EquipmentSlot slot; 17 | 18 | public EquipmentProperty(PacketFactory packetFactory, String name, EquipmentSlot slot) { 19 | super(name, null, ItemStack.class); 20 | this.packetFactory = packetFactory; 21 | this.slot = slot; 22 | } 23 | 24 | @Override 25 | public void apply(Player player, PacketEntity entity, boolean isSpawned, Map> properties) { 26 | packetFactory.sendEquipment(player, entity, new Equipment(slot, entity.getProperty(this))); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/ForceBodyRotationProperty.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.entity.properties; 2 | 3 | import com.github.retrooper.packetevents.protocol.entity.data.EntityData; 4 | import lol.pyr.znpcsplus.entity.PacketEntity; 5 | import lol.pyr.znpcsplus.scheduling.TaskScheduler; 6 | import org.bukkit.entity.Player; 7 | 8 | import java.util.Map; 9 | 10 | public class ForceBodyRotationProperty extends DummyProperty { 11 | private final TaskScheduler scheduler; 12 | 13 | public ForceBodyRotationProperty(TaskScheduler scheduler) { 14 | super("force_body_rotation", false); 15 | this.scheduler = scheduler; 16 | } 17 | 18 | @Override 19 | public void apply(Player player, PacketEntity entity, boolean isSpawned, Map> properties) { 20 | if (entity.getProperty(this)) { 21 | scheduler.runLaterAsync(() -> entity.swingHand(player, false), 2L); 22 | scheduler.runLaterAsync(() -> entity.swingHand(player, false), 6L); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/GlowProperty.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.entity.properties; 2 | 3 | import com.github.retrooper.packetevents.protocol.entity.data.EntityData; 4 | import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes; 5 | import lol.pyr.znpcsplus.entity.EntityPropertyImpl; 6 | import lol.pyr.znpcsplus.entity.PacketEntity; 7 | import lol.pyr.znpcsplus.packets.PacketFactory; 8 | import lol.pyr.znpcsplus.util.NamedColor; 9 | import org.bukkit.entity.Player; 10 | 11 | import java.util.Map; 12 | 13 | public class GlowProperty extends EntityPropertyImpl { 14 | private final PacketFactory packetFactory; 15 | 16 | public GlowProperty(PacketFactory packetFactory) { 17 | super("glow", null, NamedColor.class); 18 | this.packetFactory = packetFactory; 19 | } 20 | 21 | @Override 22 | public void apply(Player player, PacketEntity entity, boolean isSpawned, Map> properties) { 23 | NamedColor value = entity.getProperty(this); 24 | EntityData oldData = properties.get(0); 25 | // byte oldValue = oldData == null ? 0 : (byte) oldData.getValue(); 26 | byte oldValue = 0; 27 | if (oldData != null && oldData.getValue() instanceof Number) { 28 | oldValue = ((Number) oldData.getValue()).byteValue(); 29 | } 30 | properties.put(0, newEntityData(0, EntityDataTypes.BYTE, (byte) (oldValue | (value == null ? 0 : 0x40)))); 31 | // the team is already created with the right glow color in the packet factory if the npc isnt spawned yet 32 | if (isSpawned) { 33 | packetFactory.removeTeam(player, entity); 34 | packetFactory.createTeam(player, entity, value); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/HealthProperty.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.entity.properties; 2 | 3 | import com.github.retrooper.packetevents.protocol.attribute.Attributes; 4 | import com.github.retrooper.packetevents.protocol.entity.data.EntityData; 5 | import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes; 6 | import lol.pyr.znpcsplus.entity.EntityPropertyImpl; 7 | import lol.pyr.znpcsplus.entity.PacketEntity; 8 | import org.bukkit.entity.Player; 9 | 10 | import java.util.Map; 11 | 12 | public class HealthProperty extends EntityPropertyImpl { 13 | private final int index; 14 | 15 | public HealthProperty(int index) { 16 | super("health", 20f, Float.class); 17 | this.index = index; 18 | } 19 | 20 | @Override 21 | public void apply(Player player, PacketEntity entity, boolean isSpawned, Map> properties) { 22 | float health = entity.getProperty(this); 23 | health = (float) Attributes.MAX_HEALTH.sanitizeValue(health); 24 | properties.put(index, new EntityData<>(index, EntityDataTypes.FLOAT, health)); 25 | 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/HologramItemProperty.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.entity.properties; 2 | 3 | import com.github.retrooper.packetevents.protocol.entity.data.EntityData; 4 | import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes; 5 | import com.github.retrooper.packetevents.protocol.item.ItemStack; 6 | import lol.pyr.znpcsplus.entity.EntityPropertyImpl; 7 | import lol.pyr.znpcsplus.entity.PacketEntity; 8 | import org.bukkit.entity.Player; 9 | 10 | import java.util.Map; 11 | 12 | public class HologramItemProperty extends EntityPropertyImpl { 13 | 14 | public HologramItemProperty() { 15 | super("holo_item", null, ItemStack.class); 16 | setPlayerModifiable(false); 17 | } 18 | 19 | @Override 20 | public void apply(Player player, PacketEntity entity, boolean isSpawned, Map> properties) { 21 | properties.put(8, newEntityData(8, EntityDataTypes.ITEMSTACK, entity.getProperty(this))); 22 | properties.put(5, newEntityData(5, EntityDataTypes.BOOLEAN, true)); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/HorseColorProperty.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.entity.properties; 2 | 3 | import com.github.retrooper.packetevents.protocol.entity.data.EntityData; 4 | import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes; 5 | import lol.pyr.znpcsplus.entity.EntityPropertyImpl; 6 | import lol.pyr.znpcsplus.entity.PacketEntity; 7 | import lol.pyr.znpcsplus.util.HorseColor; 8 | import org.bukkit.entity.Player; 9 | 10 | import java.util.Map; 11 | 12 | public class HorseColorProperty extends EntityPropertyImpl { 13 | private final int index; 14 | 15 | public HorseColorProperty(int index) { 16 | super("horse_color", HorseColor.WHITE, HorseColor.class); 17 | this.index = index; 18 | } 19 | 20 | @Override 21 | public void apply(Player player, PacketEntity entity, boolean isSpawned, Map> properties) { 22 | EntityData oldData = properties.get(index); 23 | HorseColor value = entity.getProperty(this); 24 | int oldValue = (oldData != null && oldData.getValue() instanceof Integer) ? (Integer) oldData.getValue() : 0; 25 | 26 | int newValue = value.ordinal() | (oldValue & 0xFF00); 27 | properties.put(index, newEntityData(index, EntityDataTypes.INT, newValue)); 28 | 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/HorseStyleProperty.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.entity.properties; 2 | 3 | import com.github.retrooper.packetevents.protocol.entity.data.EntityData; 4 | import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes; 5 | import lol.pyr.znpcsplus.entity.EntityPropertyImpl; 6 | import lol.pyr.znpcsplus.entity.PacketEntity; 7 | import lol.pyr.znpcsplus.util.HorseStyle; 8 | import org.bukkit.entity.Player; 9 | 10 | import java.util.Map; 11 | 12 | public class HorseStyleProperty extends EntityPropertyImpl { 13 | private final int index; 14 | 15 | public HorseStyleProperty(int index) { 16 | super("horse_style", HorseStyle.NONE, HorseStyle.class); 17 | this.index = index; 18 | } 19 | 20 | @Override 21 | public void apply(Player player, PacketEntity entity, boolean isSpawned, Map> properties) { 22 | EntityData oldData = properties.get(index); 23 | HorseStyle value = entity.getProperty(this); 24 | 25 | int oldValue = (oldData != null && oldData.getValue() instanceof Integer) ? (Integer) oldData.getValue() : 0; 26 | int newValue = (oldValue & 0x00FF) | (value.ordinal() << 8); 27 | properties.put(index, newEntityData(index, EntityDataTypes.INT, newValue)); 28 | 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/IntegerProperty.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.entity.properties; 2 | 3 | import com.github.retrooper.packetevents.protocol.entity.data.EntityData; 4 | import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes; 5 | import lol.pyr.znpcsplus.entity.EntityPropertyImpl; 6 | import lol.pyr.znpcsplus.entity.PacketEntity; 7 | import org.bukkit.entity.Player; 8 | 9 | import java.util.Map; 10 | 11 | public class IntegerProperty extends EntityPropertyImpl { 12 | private final int index; 13 | private final boolean legacy; 14 | 15 | public IntegerProperty(String name, int index, Integer defaultValue) { 16 | this(name, index, defaultValue, false); 17 | } 18 | 19 | public IntegerProperty(String name, int index, Integer defaultValue, boolean legacy) { 20 | super(name, defaultValue, Integer.class); 21 | this.index = index; 22 | this.legacy = legacy; 23 | } 24 | 25 | @Override 26 | public void apply(Player player, PacketEntity entity, boolean isSpawned, Map> properties) { 27 | properties.put(index, legacy ? 28 | newEntityData(index, EntityDataTypes.BYTE, (byte) entity.getProperty(this).intValue()) : 29 | newEntityData(index, EntityDataTypes.INT, entity.getProperty(this))); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/LegacyBabyProperty.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.entity.properties; 2 | 3 | import com.github.retrooper.packetevents.protocol.entity.data.EntityData; 4 | import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes; 5 | import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes; 6 | import lol.pyr.znpcsplus.entity.EntityPropertyImpl; 7 | import lol.pyr.znpcsplus.entity.PacketEntity; 8 | import org.bukkit.entity.Player; 9 | 10 | import java.util.Map; 11 | 12 | public class LegacyBabyProperty extends EntityPropertyImpl { 13 | private final int index; 14 | 15 | public LegacyBabyProperty(int index) { 16 | super("baby", false, Boolean.class); 17 | this.index = index; 18 | } 19 | 20 | @Override 21 | public void apply(Player player, PacketEntity entity, boolean isSpawned, Map> properties) { 22 | boolean isBaby = entity.getProperty(this); 23 | if (entity.getType().equals(EntityTypes.ZOMBIE)) { 24 | properties.put(index, newEntityData(index, EntityDataTypes.BYTE, (byte) (isBaby ? 1 : 0))); 25 | } else { 26 | properties.put(index, newEntityData(index, EntityDataTypes.BYTE, (byte) (isBaby ? -1 : 0))); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/OptionalBlockPosProperty.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.entity.properties; 2 | 3 | import com.github.retrooper.packetevents.protocol.entity.data.EntityData; 4 | import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes; 5 | import lol.pyr.znpcsplus.entity.EntityPropertyImpl; 6 | import lol.pyr.znpcsplus.entity.PacketEntity; 7 | import lol.pyr.znpcsplus.util.Vector3i; 8 | import org.bukkit.entity.Player; 9 | 10 | import java.util.Map; 11 | import java.util.Optional; 12 | 13 | public class OptionalBlockPosProperty extends EntityPropertyImpl { 14 | private final int index; 15 | 16 | public OptionalBlockPosProperty(String name, Vector3i defaultValue, int index) { 17 | super(name, defaultValue, Vector3i.class); 18 | this.index = index; 19 | } 20 | 21 | @Override 22 | public void apply(Player player, PacketEntity entity, boolean isSpawned, Map> properties) { 23 | Vector3i value = entity.getProperty(this); 24 | if (value == null) properties.put(index, new EntityData<>(index, EntityDataTypes.OPTIONAL_BLOCK_POSITION, Optional.empty())); 25 | else properties.put(index, new EntityData<>(index, EntityDataTypes.OPTIONAL_BLOCK_POSITION, 26 | Optional.of(new com.github.retrooper.packetevents.util.Vector3i(value.getX(), value.getY(), value.getZ())))); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/RotationProperty.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.entity.properties; 2 | 3 | import com.github.retrooper.packetevents.protocol.entity.data.EntityData; 4 | import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes; 5 | import lol.pyr.znpcsplus.entity.EntityPropertyImpl; 6 | import lol.pyr.znpcsplus.entity.PacketEntity; 7 | import lol.pyr.znpcsplus.util.Vector3f; 8 | import org.bukkit.entity.Player; 9 | 10 | import java.util.Map; 11 | 12 | public class RotationProperty extends EntityPropertyImpl { 13 | private final int index; 14 | 15 | public RotationProperty(String name, int index, Vector3f defaultValue) { 16 | super(name, defaultValue, Vector3f.class); 17 | this.index = index; 18 | } 19 | 20 | @Override 21 | public void apply(Player player, PacketEntity entity, boolean isSpawned, Map> properties) { 22 | Vector3f vec = entity.getProperty(this); 23 | properties.put(index, newEntityData(index, EntityDataTypes.ROTATION, new com.github.retrooper.packetevents.util.Vector3f(vec.getX(), vec.getY(), vec.getZ()))); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/TargetNpcProperty.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.entity.properties; 2 | 3 | import com.github.retrooper.packetevents.protocol.entity.data.EntityData; 4 | import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes; 5 | import lol.pyr.znpcsplus.entity.EntityPropertyImpl; 6 | import lol.pyr.znpcsplus.entity.PacketEntity; 7 | import lol.pyr.znpcsplus.npc.NpcEntryImpl; 8 | import org.bukkit.entity.Player; 9 | 10 | import java.util.Map; 11 | 12 | public class TargetNpcProperty extends EntityPropertyImpl { 13 | private final int index; 14 | 15 | public TargetNpcProperty(String name, int index, NpcEntryImpl defaultValue) { 16 | super(name, defaultValue, NpcEntryImpl.class); 17 | this.index = index; 18 | } 19 | 20 | @Override 21 | public void apply(Player player, PacketEntity entity, boolean isSpawned, Map> properties) { 22 | NpcEntryImpl value = entity.getProperty(this); 23 | if (value == null) return; 24 | if (value.getNpc().getEntity().getEntityId() == entity.getEntityId()) return; 25 | if (value.getNpc().isVisibleTo(player)) { 26 | properties.put(index, newEntityData(index, EntityDataTypes.INT, value.getNpc().getEntity().getEntityId())); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/villager/VillagerDataProperty.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.entity.properties.villager; 2 | 3 | import com.github.retrooper.packetevents.protocol.entity.data.EntityData; 4 | import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes; 5 | import com.github.retrooper.packetevents.protocol.entity.villager.VillagerData; 6 | import com.github.retrooper.packetevents.protocol.entity.villager.profession.VillagerProfessions; 7 | import com.github.retrooper.packetevents.protocol.entity.villager.type.VillagerTypes; 8 | import lol.pyr.znpcsplus.entity.EntityPropertyImpl; 9 | import lol.pyr.znpcsplus.entity.PacketEntity; 10 | import org.bukkit.entity.Player; 11 | 12 | import java.util.Map; 13 | 14 | public abstract class VillagerDataProperty extends EntityPropertyImpl { 15 | private final int index; 16 | 17 | @SuppressWarnings("unchecked") 18 | public VillagerDataProperty(String name, int index, T def) { 19 | super(name, def, (Class) def.getClass()); 20 | this.index = index; 21 | } 22 | 23 | @Override 24 | public void apply(Player player, PacketEntity entity, boolean isSpawned, Map> properties) { 25 | EntityData oldData = properties.get(index); 26 | VillagerData old = oldData == null ? new VillagerData(VillagerTypes.PLAINS, VillagerProfessions.NONE, 1) : (VillagerData) oldData.getValue(); 27 | properties.put(index, newEntityData(index, EntityDataTypes.VILLAGER_DATA, apply(old, entity.getProperty(this)))); 28 | } 29 | 30 | protected abstract VillagerData apply(VillagerData data, T value); 31 | } -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/villager/VillagerLevelProperty.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.entity.properties.villager; 2 | 3 | import com.github.retrooper.packetevents.protocol.entity.villager.VillagerData; 4 | import lol.pyr.znpcsplus.util.VillagerLevel; 5 | 6 | public class VillagerLevelProperty extends VillagerDataProperty { 7 | public VillagerLevelProperty(String name, int index, VillagerLevel def) { 8 | super(name, index, def); 9 | } 10 | 11 | @Override 12 | protected VillagerData apply(VillagerData data, VillagerLevel value) { 13 | data.setLevel(value.ordinal() + 1); 14 | return data; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/villager/VillagerProfessionProperty.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.entity.properties.villager; 2 | 3 | import com.github.retrooper.packetevents.protocol.entity.villager.VillagerData; 4 | import com.github.retrooper.packetevents.protocol.entity.villager.profession.VillagerProfessions; 5 | import lol.pyr.znpcsplus.util.VillagerProfession; 6 | 7 | public class VillagerProfessionProperty extends VillagerDataProperty { 8 | public VillagerProfessionProperty(String name, int index, VillagerProfession def) { 9 | super(name, index, def); 10 | } 11 | 12 | @Override 13 | protected VillagerData apply(VillagerData data, VillagerProfession value) { 14 | data.setProfession(VillagerProfessions.getById(value.getId())); 15 | return data; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/villager/VillagerTypeProperty.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.entity.properties.villager; 2 | 3 | import com.github.retrooper.packetevents.protocol.entity.villager.VillagerData; 4 | import com.github.retrooper.packetevents.protocol.entity.villager.type.VillagerTypes; 5 | import lol.pyr.znpcsplus.util.VillagerType; 6 | 7 | public class VillagerTypeProperty extends VillagerDataProperty { 8 | public VillagerTypeProperty(String name, int index, VillagerType def) { 9 | super(name, index, def); 10 | } 11 | 12 | @Override 13 | protected VillagerData apply(VillagerData data, VillagerType value) { 14 | data.setType(VillagerTypes.getById(value.getId())); 15 | return data; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/entity/serializers/BlockStatePropertySerializer.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.entity.serializers; 2 | 3 | import lol.pyr.znpcsplus.entity.PropertySerializer; 4 | import lol.pyr.znpcsplus.util.BlockState; 5 | 6 | public class BlockStatePropertySerializer implements PropertySerializer { 7 | @Override 8 | public String serialize(BlockState property) { 9 | return String.valueOf(property.getGlobalId()); 10 | } 11 | 12 | @Override 13 | public BlockState deserialize(String property) { 14 | try { 15 | int id = Integer.parseInt(property); 16 | return new BlockState(id); 17 | } catch (Exception e) { 18 | e.printStackTrace(); 19 | } 20 | return new BlockState(0); 21 | } 22 | 23 | @Override 24 | public Class getTypeClass() { 25 | return BlockState.class; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/entity/serializers/BooleanPropertySerializer.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.entity.serializers; 2 | 3 | import lol.pyr.znpcsplus.entity.PropertySerializer; 4 | 5 | public class BooleanPropertySerializer implements PropertySerializer { 6 | @Override 7 | public String serialize(Boolean property) { 8 | return String.valueOf(property); 9 | } 10 | 11 | @Override 12 | public Boolean deserialize(String property) { 13 | return Boolean.valueOf(property); 14 | } 15 | 16 | @Override 17 | public Class getTypeClass() { 18 | return Boolean.class; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/entity/serializers/ColorPropertySerializer.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.entity.serializers; 2 | 3 | import lol.pyr.znpcsplus.entity.PropertySerializer; 4 | import org.bukkit.Color; 5 | 6 | public class ColorPropertySerializer implements PropertySerializer { 7 | @Override 8 | public String serialize(Color property) { 9 | return String.valueOf(property.asRGB()); 10 | } 11 | 12 | @Override 13 | public Color deserialize(String property) { 14 | return Color.fromRGB(Integer.parseInt(property)); 15 | } 16 | 17 | @Override 18 | public Class getTypeClass() { 19 | return Color.class; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/entity/serializers/ComponentPropertySerializer.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.entity.serializers; 2 | 3 | import lol.pyr.znpcsplus.entity.PropertySerializer; 4 | import net.kyori.adventure.text.Component; 5 | import net.kyori.adventure.text.minimessage.MiniMessage; 6 | 7 | import java.nio.charset.StandardCharsets; 8 | import java.util.Base64; 9 | 10 | public class ComponentPropertySerializer implements PropertySerializer { 11 | @Override 12 | public String serialize(Component property) { 13 | return Base64.getEncoder().encodeToString(MiniMessage.miniMessage().serialize(property).getBytes(StandardCharsets.UTF_8)); 14 | } 15 | 16 | @Override 17 | public Component deserialize(String property) { 18 | return MiniMessage.miniMessage().deserialize(new String(Base64.getDecoder().decode(property), StandardCharsets.UTF_8)); 19 | } 20 | 21 | @Override 22 | public Class getTypeClass() { 23 | return Component.class; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/entity/serializers/GenericSerializer.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.entity.serializers; 2 | 3 | import lol.pyr.znpcsplus.entity.PropertySerializer; 4 | 5 | import java.util.function.Function; 6 | 7 | public class GenericSerializer implements PropertySerializer { 8 | private final Function encoder; 9 | private final Function decoder; 10 | private final Class typeClass; 11 | 12 | public GenericSerializer(Function encoder, Function decoder, Class typeClass) { 13 | this.encoder = encoder; 14 | this.decoder = decoder; 15 | this.typeClass = typeClass; 16 | } 17 | 18 | @Override 19 | public String serialize(T property) { 20 | return encoder.apply(property); 21 | } 22 | 23 | @Override 24 | public T deserialize(String property) { 25 | return decoder.apply(property); 26 | } 27 | 28 | @Override 29 | public Class getTypeClass() { 30 | return typeClass; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/entity/serializers/ItemStackPropertySerializer.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.entity.serializers; 2 | 3 | import com.github.retrooper.packetevents.protocol.item.ItemStack; 4 | import io.github.retrooper.packetevents.util.SpigotConversionUtil; 5 | import lol.pyr.znpcsplus.entity.PropertySerializer; 6 | import lol.pyr.znpcsplus.util.ItemSerializationUtil; 7 | 8 | public class ItemStackPropertySerializer implements PropertySerializer { 9 | @Override 10 | public String serialize(ItemStack property) { 11 | return ItemSerializationUtil.itemToB64(SpigotConversionUtil.toBukkitItemStack(property)); 12 | } 13 | 14 | @Override 15 | public ItemStack deserialize(String property) { 16 | return SpigotConversionUtil.fromBukkitItemStack(ItemSerializationUtil.itemFromB64(property)); 17 | } 18 | 19 | @Override 20 | public Class getTypeClass() { 21 | return ItemStack.class; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/entity/serializers/LookTypeSerializer.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.entity.serializers; 2 | 3 | import lol.pyr.znpcsplus.entity.PropertySerializer; 4 | import lol.pyr.znpcsplus.util.LookType; 5 | 6 | public class LookTypeSerializer implements PropertySerializer { 7 | @Override 8 | public String serialize(LookType property) { 9 | return property.name(); 10 | } 11 | 12 | @Override 13 | public LookType deserialize(String property) { 14 | if (property.equals("true")) return LookType.CLOSEST_PLAYER; 15 | try { 16 | return LookType.valueOf(property); 17 | } catch (IllegalArgumentException ignored) { 18 | return LookType.FIXED; 19 | } 20 | } 21 | 22 | @Override 23 | public Class getTypeClass() { 24 | return LookType.class; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/entity/serializers/NamedColorPropertySerializer.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.entity.serializers; 2 | 3 | import lol.pyr.znpcsplus.entity.PropertySerializer; 4 | import lol.pyr.znpcsplus.util.NamedColor; 5 | 6 | public class NamedColorPropertySerializer implements PropertySerializer { 7 | @Override 8 | public String serialize(NamedColor property) { 9 | return property.name(); 10 | } 11 | 12 | @Override 13 | public NamedColor deserialize(String property) { 14 | try { 15 | return NamedColor.valueOf(property.toUpperCase()); 16 | } catch (IllegalArgumentException exception) { 17 | return NamedColor.WHITE; 18 | } 19 | } 20 | 21 | @Override 22 | public Class getTypeClass() { 23 | return NamedColor.class; 24 | } 25 | } -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/entity/serializers/SkinDescriptorSerializer.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.entity.serializers; 2 | 3 | import lol.pyr.znpcsplus.api.skin.SkinDescriptor; 4 | import lol.pyr.znpcsplus.entity.PropertySerializer; 5 | import lol.pyr.znpcsplus.skin.BaseSkinDescriptor; 6 | import lol.pyr.znpcsplus.skin.cache.MojangSkinCache; 7 | 8 | public class SkinDescriptorSerializer implements PropertySerializer { 9 | private final MojangSkinCache skinCache; 10 | 11 | public SkinDescriptorSerializer(MojangSkinCache skinCache) { 12 | this.skinCache = skinCache; 13 | } 14 | 15 | @Override 16 | public String serialize(SkinDescriptor property) { 17 | return ((BaseSkinDescriptor) property).serialize(); 18 | } 19 | 20 | @Override 21 | public SkinDescriptor deserialize(String property) { 22 | return BaseSkinDescriptor.deserialize(skinCache, property); 23 | } 24 | 25 | @Override 26 | public Class getTypeClass() { 27 | return SkinDescriptor.class; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/entity/serializers/TargetNpcPropertySerializer.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.entity.serializers; 2 | 3 | import lol.pyr.znpcsplus.entity.PropertySerializer; 4 | import lol.pyr.znpcsplus.npc.NpcEntryImpl; 5 | 6 | public class TargetNpcPropertySerializer implements PropertySerializer { 7 | @Override 8 | public String serialize(NpcEntryImpl property) { 9 | return property.getId(); 10 | } 11 | 12 | @Override 13 | public NpcEntryImpl deserialize(String property) { 14 | return null; // TODO: find a way to do this 15 | } 16 | 17 | @Override 18 | public Class getTypeClass() { 19 | return NpcEntryImpl.class; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/entity/serializers/Vector3fPropertySerializer.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.entity.serializers; 2 | 3 | import lol.pyr.znpcsplus.entity.PropertySerializer; 4 | import lol.pyr.znpcsplus.util.Vector3f; 5 | 6 | public class Vector3fPropertySerializer implements PropertySerializer { 7 | 8 | @Override 9 | public String serialize(Vector3f property) { 10 | return property.toString(); 11 | } 12 | 13 | @Override 14 | public Vector3f deserialize(String property) { 15 | return new Vector3f(property); 16 | } 17 | 18 | @Override 19 | public Class getTypeClass() { 20 | return Vector3f.class; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/hologram/HologramText.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.hologram; 2 | 3 | import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes; 4 | import lol.pyr.znpcsplus.api.entity.EntityProperty; 5 | import lol.pyr.znpcsplus.entity.EntityPropertyRegistryImpl; 6 | import lol.pyr.znpcsplus.packets.PacketFactory; 7 | import lol.pyr.znpcsplus.util.NpcLocation; 8 | import lol.pyr.znpcsplus.util.Viewable; 9 | import net.kyori.adventure.text.Component; 10 | import org.bukkit.entity.Player; 11 | 12 | import java.util.concurrent.CompletableFuture; 13 | 14 | public class HologramText extends HologramLine { 15 | 16 | private static final Component BLANK = Component.text("%blank%"); 17 | 18 | public HologramText(Viewable viewable, EntityPropertyRegistryImpl propertyRegistry, PacketFactory packetFactory, NpcLocation location, Component text) { 19 | super(viewable, text, packetFactory, EntityTypes.ARMOR_STAND, location); 20 | addProperty(propertyRegistry.getByName("name")); 21 | addProperty(propertyRegistry.getByName("invisible")); 22 | } 23 | 24 | @Override 25 | public CompletableFuture show(Player player) { 26 | if (getValue().equals(BLANK)) return CompletableFuture.completedFuture(null); 27 | return super.show(player); 28 | } 29 | 30 | @SuppressWarnings("unchecked") 31 | @Override 32 | public T getProperty(EntityProperty key) { 33 | if (key.getName().equalsIgnoreCase("invisible")) return (T) Boolean.TRUE; 34 | if (key.getName().equalsIgnoreCase("name")) return (T) getValue(); 35 | return super.getProperty(key); 36 | } 37 | 38 | @Override 39 | public boolean hasProperty(EntityProperty key) { 40 | return key.getName().equalsIgnoreCase("name") || key.getName().equalsIgnoreCase("invisible"); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/interaction/InteractionActionImpl.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.interaction; 2 | 3 | import lol.pyr.director.adventure.command.CommandContext; 4 | import lol.pyr.znpcsplus.api.interaction.InteractionAction; 5 | import lol.pyr.znpcsplus.api.interaction.InteractionType; 6 | import net.kyori.adventure.text.Component; 7 | 8 | public abstract class InteractionActionImpl extends InteractionAction { 9 | protected InteractionActionImpl(long cooldown, long delay, InteractionType interactionType) { 10 | super(cooldown, delay, interactionType); 11 | } 12 | 13 | public abstract Component getInfo(String id, int index, CommandContext context); 14 | } 15 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/interaction/InteractionCommandHandler.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.interaction; 2 | 3 | import lol.pyr.director.adventure.command.CommandContext; 4 | import lol.pyr.director.adventure.command.CommandHandler; 5 | import lol.pyr.director.common.command.CommandExecutionException; 6 | import lol.pyr.znpcsplus.api.interaction.InteractionAction; 7 | import lol.pyr.znpcsplus.npc.NpcEntryImpl; 8 | import lol.pyr.znpcsplus.npc.NpcImpl; 9 | import net.kyori.adventure.text.Component; 10 | import net.kyori.adventure.text.format.NamedTextColor; 11 | 12 | public interface InteractionCommandHandler extends CommandHandler { 13 | String getSubcommandName(); 14 | 15 | InteractionAction parse(CommandContext context) throws CommandExecutionException; 16 | void appendUsage(CommandContext context); 17 | 18 | @Override 19 | default void run(CommandContext context) throws CommandExecutionException { 20 | appendUsage(context); 21 | NpcImpl npc = context.parse(NpcEntryImpl.class).getNpc(); 22 | npc.addAction(parse(context)); 23 | context.send(Component.text("Added action to npc", NamedTextColor.GREEN)); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcEntryImpl.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.npc; 2 | 3 | import lol.pyr.znpcsplus.api.npc.NpcEntry; 4 | 5 | public class NpcEntryImpl implements NpcEntry { 6 | private final String id; 7 | private final NpcImpl npc; 8 | 9 | private boolean process = false; 10 | private boolean save = false; 11 | private boolean modify = false; 12 | 13 | public NpcEntryImpl(String id, NpcImpl npc) { 14 | this.id = id.toLowerCase(); 15 | this.npc = npc; 16 | } 17 | 18 | @Override 19 | public NpcImpl getNpc() { 20 | return npc; 21 | } 22 | 23 | @Override 24 | public boolean isProcessed() { 25 | return process; 26 | } 27 | 28 | @Override 29 | public void setProcessed(boolean value) { 30 | if (process && !value) npc.delete(); 31 | process = value; 32 | } 33 | 34 | @Override 35 | public boolean isSave() { 36 | return save; 37 | } 38 | 39 | @Override 40 | public void setSave(boolean value) { 41 | save = value; 42 | } 43 | 44 | @Override 45 | public boolean isAllowCommandModification() { 46 | return modify; 47 | } 48 | 49 | @Override 50 | public void setAllowCommandModification(boolean value) { 51 | modify = value; 52 | } 53 | 54 | public void enableEverything() { 55 | setSave(true); 56 | setProcessed(true); 57 | setAllowCommandModification(true); 58 | } 59 | 60 | public String getId() { 61 | return id; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/packets/PacketFactory.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.packets; 2 | 3 | import com.github.retrooper.packetevents.protocol.entity.data.EntityData; 4 | import com.github.retrooper.packetevents.protocol.player.Equipment; 5 | import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerUpdateAttributes; 6 | import lol.pyr.znpcsplus.api.entity.PropertyHolder; 7 | import lol.pyr.znpcsplus.entity.PacketEntity; 8 | import lol.pyr.znpcsplus.util.NamedColor; 9 | import org.bukkit.entity.Player; 10 | 11 | import java.util.List; 12 | import java.util.concurrent.CompletableFuture; 13 | 14 | public interface PacketFactory { 15 | CompletableFuture spawnPlayer(Player player, PacketEntity entity, PropertyHolder properties); 16 | void spawnEntity(Player player, PacketEntity entity, PropertyHolder properties); 17 | void destroyEntity(Player player, PacketEntity entity, PropertyHolder properties); 18 | void teleportEntity(Player player, PacketEntity entity); 19 | CompletableFuture addTabPlayer(Player player, PacketEntity entity, PropertyHolder properties); 20 | void removeTabPlayer(Player player, PacketEntity entity); 21 | void createTeam(Player player, PacketEntity entity, NamedColor namedColor); 22 | void removeTeam(Player player, PacketEntity entity); 23 | void sendAllMetadata(Player player, PacketEntity entity, PropertyHolder properties); 24 | void sendEquipment(Player player, PacketEntity entity, Equipment equipment); 25 | void sendMetadata(Player player, PacketEntity entity, List> data); 26 | void sendHeadRotation(Player player, PacketEntity entity, float yaw, float pitch); 27 | void sendHandSwing(Player player, PacketEntity entity, boolean offHand); 28 | void setPassengers(Player player, int vehicle, int... passengers); 29 | void sendAllAttributes(Player player, PacketEntity entity, PropertyHolder properties); 30 | void sendAttribute(Player player, PacketEntity entity, WrapperPlayServerUpdateAttributes.Property property); 31 | } 32 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/packets/V1_21_3PacketFactory.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.packets; 2 | 3 | import com.github.retrooper.packetevents.PacketEventsAPI; 4 | import com.github.retrooper.packetevents.protocol.entity.EntityPositionData; 5 | import com.github.retrooper.packetevents.protocol.teleport.RelativeFlag; 6 | import com.github.retrooper.packetevents.util.Vector3d; 7 | import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityHeadLook; 8 | import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityTeleport; 9 | import lol.pyr.znpcsplus.config.ConfigManager; 10 | import lol.pyr.znpcsplus.entity.EntityPropertyRegistryImpl; 11 | import lol.pyr.znpcsplus.entity.PacketEntity; 12 | import lol.pyr.znpcsplus.scheduling.TaskScheduler; 13 | import lol.pyr.znpcsplus.util.NpcLocation; 14 | import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; 15 | import org.bukkit.entity.Player; 16 | import org.bukkit.plugin.Plugin; 17 | 18 | public class V1_21_3PacketFactory extends V1_20_2PacketFactory { 19 | public V1_21_3PacketFactory(TaskScheduler scheduler, PacketEventsAPI packetEvents, EntityPropertyRegistryImpl propertyRegistry, LegacyComponentSerializer textSerializer, ConfigManager configManager) { 20 | super(scheduler, packetEvents, propertyRegistry, textSerializer, configManager); 21 | } 22 | 23 | @Override 24 | public void teleportEntity(Player player, PacketEntity entity) { 25 | NpcLocation location = entity.getLocation(); 26 | sendPacket(player, new WrapperPlayServerEntityTeleport(entity.getEntityId(), new EntityPositionData(npcLocationToVector(location), new Vector3d(0, 0, 0), location.getYaw(), location.getPitch()), RelativeFlag.NONE, false)); 27 | sendPacket(player, new WrapperPlayServerEntityHeadLook(entity.getEntityId(), location.getYaw())); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/parsers/ColorParser.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.parsers; 2 | 3 | import lol.pyr.director.adventure.command.CommandContext; 4 | import lol.pyr.director.adventure.parse.ParserType; 5 | import lol.pyr.director.common.command.CommandExecutionException; 6 | import lol.pyr.director.common.message.Message; 7 | import org.bukkit.Color; 8 | 9 | import java.util.Deque; 10 | 11 | public class ColorParser extends ParserType { 12 | public ColorParser(Message message) { 13 | super(message); 14 | } 15 | 16 | @Override 17 | public Color parse(Deque deque) throws CommandExecutionException { 18 | String color = deque.pop(); 19 | if (color.startsWith("0x")) color = color.substring(2); 20 | if (color.startsWith("&")) color = color.substring(1); 21 | if (color.startsWith("#")) color = color.substring(1); 22 | try { 23 | return Color.fromRGB(Integer.parseInt(color, 16)); 24 | } catch (IllegalArgumentException exception) { 25 | throw new CommandExecutionException(); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/parsers/EntityPropertyParser.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.parsers; 2 | 3 | import lol.pyr.director.adventure.command.CommandContext; 4 | import lol.pyr.director.adventure.parse.ParserType; 5 | import lol.pyr.director.common.command.CommandExecutionException; 6 | import lol.pyr.director.common.message.Message; 7 | import lol.pyr.znpcsplus.entity.EntityPropertyImpl; 8 | import lol.pyr.znpcsplus.entity.EntityPropertyRegistryImpl; 9 | 10 | import java.util.Deque; 11 | 12 | @SuppressWarnings("rawtypes") 13 | public class EntityPropertyParser extends ParserType*/> { 14 | private final EntityPropertyRegistryImpl propertyRegistry; 15 | 16 | public EntityPropertyParser(Message message, EntityPropertyRegistryImpl propertyRegistry) { 17 | super(message); 18 | this.propertyRegistry = propertyRegistry; 19 | } 20 | 21 | @Override 22 | public EntityPropertyImpl parse(Deque deque) throws CommandExecutionException { 23 | EntityPropertyImpl property = propertyRegistry.getByName(deque.pop()); 24 | if (property == null) throw new CommandExecutionException(); 25 | return property; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/parsers/EnumParser.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.parsers; 2 | 3 | import lol.pyr.director.adventure.command.CommandContext; 4 | import lol.pyr.director.adventure.parse.ParserType; 5 | import lol.pyr.director.common.command.CommandExecutionException; 6 | import lol.pyr.director.common.message.Message; 7 | 8 | import java.util.Deque; 9 | 10 | public class EnumParser> extends ParserType { 11 | 12 | private final Class enumClass; 13 | 14 | public EnumParser(Class enumClass, Message message) { 15 | super(message); 16 | this.enumClass = enumClass; 17 | } 18 | 19 | @Override 20 | public T parse(Deque deque) throws CommandExecutionException { 21 | try { 22 | return Enum.valueOf(enumClass, deque.pop().toUpperCase()); 23 | } catch (IllegalArgumentException e) { 24 | throw new CommandExecutionException(); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/parsers/InteractionTypeParser.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.parsers; 2 | 3 | import lol.pyr.director.adventure.command.CommandContext; 4 | import lol.pyr.director.adventure.parse.ParserType; 5 | import lol.pyr.director.common.command.CommandExecutionException; 6 | import lol.pyr.director.common.message.Message; 7 | import lol.pyr.znpcsplus.api.interaction.InteractionType; 8 | 9 | import java.util.Deque; 10 | 11 | public class InteractionTypeParser extends ParserType { 12 | public InteractionTypeParser(Message message) { 13 | super(message); 14 | } 15 | 16 | @Override 17 | public InteractionType parse(Deque deque) throws CommandExecutionException { 18 | try { 19 | return InteractionType.valueOf(deque.pop().toUpperCase()); 20 | } catch (IllegalArgumentException ignored) { 21 | throw new CommandExecutionException(); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/parsers/NamedColorParser.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.parsers; 2 | 3 | import lol.pyr.director.adventure.command.CommandContext; 4 | import lol.pyr.director.adventure.parse.ParserType; 5 | import lol.pyr.director.common.command.CommandExecutionException; 6 | import lol.pyr.director.common.message.Message; 7 | import lol.pyr.znpcsplus.util.NamedColor; 8 | import java.util.Deque; 9 | 10 | public class NamedColorParser extends ParserType { 11 | public NamedColorParser(Message message) { 12 | super(message); 13 | } 14 | 15 | @Override 16 | public NamedColor parse(Deque deque) throws CommandExecutionException { 17 | try { 18 | return NamedColor.valueOf(deque.pop()); 19 | } catch (IllegalArgumentException exception) { 20 | throw new CommandExecutionException(); 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/parsers/NpcEntryParser.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.parsers; 2 | 3 | import lol.pyr.director.adventure.command.CommandContext; 4 | import lol.pyr.director.adventure.parse.ParserType; 5 | import lol.pyr.director.common.command.CommandExecutionException; 6 | import lol.pyr.director.common.message.Message; 7 | import lol.pyr.znpcsplus.npc.NpcEntryImpl; 8 | import lol.pyr.znpcsplus.npc.NpcRegistryImpl; 9 | 10 | import java.util.Deque; 11 | 12 | public class NpcEntryParser extends ParserType { 13 | private final NpcRegistryImpl npcRegistry; 14 | 15 | public NpcEntryParser(NpcRegistryImpl npcRegistry, Message message) { 16 | super(message); 17 | this.npcRegistry = npcRegistry; 18 | } 19 | 20 | @Override 21 | public NpcEntryImpl parse(Deque deque) throws CommandExecutionException { 22 | NpcEntryImpl entry = npcRegistry.getById(deque.pop()); 23 | if (entry == null || !entry.isAllowCommandModification()) throw new CommandExecutionException(); 24 | return entry; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/parsers/NpcTypeParser.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.parsers; 2 | 3 | import lol.pyr.director.adventure.command.CommandContext; 4 | import lol.pyr.director.adventure.parse.ParserType; 5 | import lol.pyr.director.common.command.CommandExecutionException; 6 | import lol.pyr.director.common.message.Message; 7 | import lol.pyr.znpcsplus.npc.NpcTypeImpl; 8 | import lol.pyr.znpcsplus.npc.NpcTypeRegistryImpl; 9 | 10 | import java.util.Deque; 11 | 12 | public class NpcTypeParser extends ParserType { 13 | private final NpcTypeRegistryImpl typeRegistry; 14 | 15 | public NpcTypeParser(Message message, NpcTypeRegistryImpl typeRegistry) { 16 | super(message); 17 | this.typeRegistry = typeRegistry; 18 | } 19 | 20 | @Override 21 | public NpcTypeImpl parse(Deque deque) throws CommandExecutionException { 22 | NpcTypeImpl type = typeRegistry.getByName(deque.pop()); 23 | if (type == null) throw new CommandExecutionException(); 24 | return type; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/parsers/StringParser.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.parsers; 2 | 3 | import lol.pyr.director.adventure.command.CommandContext; 4 | import lol.pyr.director.adventure.parse.ParserType; 5 | import lol.pyr.director.common.command.CommandExecutionException; 6 | import lol.pyr.director.common.message.Message; 7 | 8 | import java.util.Deque; 9 | 10 | public class StringParser extends ParserType { 11 | public StringParser(Message message) { 12 | super(message); 13 | } 14 | 15 | @Override 16 | public String parse(Deque deque) throws CommandExecutionException { 17 | return String.join(" ", deque); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/parsers/Vector3fParser.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.parsers; 2 | 3 | import lol.pyr.director.adventure.command.CommandContext; 4 | import lol.pyr.director.adventure.parse.ParserType; 5 | import lol.pyr.director.common.command.CommandExecutionException; 6 | import lol.pyr.director.common.message.Message; 7 | import lol.pyr.znpcsplus.util.Vector3f; 8 | 9 | import java.util.Deque; 10 | 11 | public class Vector3fParser extends ParserType { 12 | public Vector3fParser(Message message) { 13 | super(message); 14 | } 15 | 16 | @Override 17 | public Vector3f parse(Deque deque) throws CommandExecutionException { 18 | try { 19 | return new Vector3f( 20 | Float.parseFloat(deque.pop()), 21 | Float.parseFloat(deque.pop()), 22 | Float.parseFloat(deque.pop())); 23 | } catch (NumberFormatException e) { 24 | throw new CommandExecutionException(); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/parsers/Vector3iParser.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.parsers; 2 | 3 | import lol.pyr.director.adventure.command.CommandContext; 4 | import lol.pyr.director.adventure.parse.ParserType; 5 | import lol.pyr.director.common.command.CommandExecutionException; 6 | import lol.pyr.director.common.message.Message; 7 | import lol.pyr.znpcsplus.util.Vector3i; 8 | 9 | import java.util.Deque; 10 | 11 | public class Vector3iParser extends ParserType { 12 | public Vector3iParser(Message message) { 13 | super(message); 14 | } 15 | 16 | @Override 17 | public Vector3i parse(Deque deque) throws CommandExecutionException { 18 | if (deque.size() == 0) { 19 | return null; 20 | } 21 | try { 22 | return new Vector3i( 23 | Integer.parseInt(deque.pop()), 24 | Integer.parseInt(deque.pop()), 25 | Integer.parseInt(deque.pop())); 26 | } catch (NumberFormatException e) { 27 | throw new CommandExecutionException(); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/reflection/ReflectionPackage.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.reflection; 2 | 3 | import com.github.retrooper.packetevents.PacketEvents; 4 | import com.github.retrooper.packetevents.manager.server.ServerVersion; 5 | import org.bukkit.Bukkit; 6 | 7 | import java.util.Arrays; 8 | import java.util.Objects; 9 | import java.util.stream.Collectors; 10 | 11 | /** 12 | * A class containing getAll of the packages of the server jar that we import classes from. 13 | * Every line has a check for the "flattened" variable due to the fact that server jars 14 | * pre-1.17 had all of their classes "flattened" into one package. 15 | */ 16 | public class ReflectionPackage { 17 | private static final String VERSION = generateVersion(); 18 | public static final String BUKKIT = "org.bukkit.craftbukkit" + VERSION; 19 | private static final boolean flattened = !PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_17); 20 | 21 | /** 22 | * Check if the classes are flattened, if so we need to add the version string into the 23 | * package string which is another quirk of the old server jars. 24 | */ 25 | public static final String MINECRAFT = joinWithDot("net.minecraft", flattened ? "server" + VERSION : ""); 26 | public static final String ENTITY = flattened ? MINECRAFT : joinWithDot(MINECRAFT, "world.entity"); 27 | 28 | public static String joinWithDot(String... parts) { 29 | return Arrays.stream(parts) 30 | .filter(Objects::nonNull) 31 | .filter(p -> !p.isEmpty()) 32 | .collect(Collectors.joining(".")); 33 | } 34 | 35 | private static String generateVersion() { 36 | String[] parts = Bukkit.getServer().getClass().getPackage().getName().split("\\."); 37 | if (parts.length > 3) return "." + parts[3]; 38 | return ""; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/reflection/types/ClassReflection.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.reflection.types; 2 | 3 | import lol.pyr.znpcsplus.reflection.ReflectionBuilder; 4 | import lol.pyr.znpcsplus.reflection.ReflectionLazyLoader; 5 | 6 | public class ClassReflection extends ReflectionLazyLoader> { 7 | public ClassReflection(ReflectionBuilder reflectionBuilder) { 8 | super(reflectionBuilder); 9 | } 10 | 11 | protected Class load() { 12 | return this.reflectionClasses.size() > 0 ? this.reflectionClasses.get(0) : null; 13 | } 14 | } -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/scheduling/SpigotScheduler.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.scheduling; 2 | 3 | import org.bukkit.Bukkit; 4 | import org.bukkit.entity.Player; 5 | import org.bukkit.plugin.Plugin; 6 | 7 | public class SpigotScheduler extends TaskScheduler { 8 | public SpigotScheduler(Plugin plugin) { 9 | super(plugin); 10 | } 11 | 12 | @Override 13 | public void schedulePlayerChat(Player player, String chat) { 14 | runSyncGlobal(() -> player.chat(chat)); 15 | } 16 | 17 | @Override 18 | public void schedulePlayerCommand(Player player, String command) { 19 | runSyncGlobal(() -> Bukkit.dispatchCommand(player, command)); 20 | } 21 | 22 | @Override 23 | public void runSyncGlobal(Runnable runnable) { 24 | Bukkit.getScheduler().runTask(plugin, runnable); 25 | } 26 | 27 | @Override 28 | public void runAsyncGlobal(Runnable runnable) { 29 | Bukkit.getScheduler().runTaskAsynchronously(plugin, runnable); 30 | } 31 | 32 | @Override 33 | public void runLaterAsync(Runnable runnable, long delay) { 34 | Bukkit.getScheduler().runTaskLaterAsynchronously(plugin, runnable, delay); 35 | } 36 | 37 | @Override 38 | public void runDelayedTimerAsync(Runnable runnable, long delay, long interval) { 39 | Bukkit.getScheduler().runTaskTimerAsynchronously(plugin, runnable, delay, interval); 40 | } 41 | 42 | @Override 43 | public void cancelAll() { 44 | Bukkit.getScheduler().cancelTasks(plugin); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/scheduling/TaskScheduler.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.scheduling; 2 | 3 | import org.bukkit.entity.Player; 4 | import org.bukkit.plugin.Plugin; 5 | 6 | public abstract class TaskScheduler { 7 | protected final Plugin plugin; 8 | 9 | public TaskScheduler(Plugin plugin) { 10 | this.plugin = plugin; 11 | } 12 | 13 | public abstract void schedulePlayerChat(Player player, String message); 14 | public abstract void schedulePlayerCommand(Player player, String command); 15 | public abstract void runSyncGlobal(Runnable runnable); 16 | public abstract void runAsyncGlobal(Runnable runnable); 17 | public abstract void runLaterAsync(Runnable runnable, long delay); 18 | public abstract void runDelayedTimerAsync(Runnable runnable, long delay, long interval); 19 | public abstract void cancelAll(); 20 | } 21 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/serialization/NpcSerializerRegistryImpl.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.serialization; 2 | 3 | import lol.pyr.znpcsplus.api.serialization.NpcSerializer; 4 | import lol.pyr.znpcsplus.api.serialization.NpcSerializerRegistry; 5 | import lol.pyr.znpcsplus.config.ConfigManager; 6 | import lol.pyr.znpcsplus.entity.EntityPropertyRegistryImpl; 7 | import lol.pyr.znpcsplus.interaction.ActionRegistryImpl; 8 | import lol.pyr.znpcsplus.npc.NpcTypeRegistryImpl; 9 | import lol.pyr.znpcsplus.packets.PacketFactory; 10 | import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; 11 | import org.bukkit.configuration.file.YamlConfiguration; 12 | 13 | import java.util.HashMap; 14 | import java.util.Map; 15 | 16 | public class NpcSerializerRegistryImpl implements NpcSerializerRegistry { 17 | private final Map, NpcSerializer> serializerMap = new HashMap<>(); 18 | 19 | public NpcSerializerRegistryImpl(PacketFactory packetFactory, ConfigManager configManager, ActionRegistryImpl actionRegistry, NpcTypeRegistryImpl typeRegistry, EntityPropertyRegistryImpl propertyRegistry, LegacyComponentSerializer textSerializer) { 20 | registerSerializer(YamlConfiguration.class, new YamlSerializer(packetFactory, configManager, actionRegistry, typeRegistry, propertyRegistry, textSerializer)); 21 | } 22 | 23 | @SuppressWarnings("unchecked") 24 | @Override 25 | public NpcSerializer getSerializer(Class clazz) { 26 | return (NpcSerializer) serializerMap.get(clazz); 27 | } 28 | 29 | @Override 30 | public void registerSerializer(Class clazz, NpcSerializer serializer) { 31 | serializerMap.put(clazz, serializer); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/skin/cache/CachedId.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.skin.cache; 2 | 3 | public class CachedId { 4 | private final long timestamp = System.currentTimeMillis(); 5 | private final String id; 6 | 7 | public CachedId(String id) { 8 | this.id = id; 9 | } 10 | 11 | public boolean isExpired() { 12 | return System.currentTimeMillis() - timestamp > 60000L; 13 | } 14 | 15 | public String getId() { 16 | return id; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/skin/cache/SkinCacheCleanTask.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.skin.cache; 2 | 3 | import org.bukkit.scheduler.BukkitRunnable; 4 | 5 | public class SkinCacheCleanTask extends BukkitRunnable { 6 | private final MojangSkinCache skinCache; 7 | 8 | public SkinCacheCleanTask(MojangSkinCache skinCache) { 9 | this.skinCache = skinCache; 10 | } 11 | 12 | @Override 13 | public void run() { 14 | skinCache.cleanCache(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/skin/descriptor/MirrorDescriptor.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.skin.descriptor; 2 | 3 | import lol.pyr.znpcsplus.api.skin.SkinDescriptor; 4 | import lol.pyr.znpcsplus.skin.BaseSkinDescriptor; 5 | import lol.pyr.znpcsplus.skin.SkinImpl; 6 | import lol.pyr.znpcsplus.skin.cache.MojangSkinCache; 7 | import org.bukkit.entity.Player; 8 | 9 | import java.util.concurrent.CompletableFuture; 10 | 11 | public class MirrorDescriptor implements BaseSkinDescriptor, SkinDescriptor { 12 | private final MojangSkinCache skinCache; 13 | 14 | public MirrorDescriptor(MojangSkinCache skinCache) { 15 | this.skinCache = skinCache; 16 | } 17 | 18 | @Override 19 | public CompletableFuture fetch(Player player) { 20 | return CompletableFuture.completedFuture(skinCache.getFromPlayer(player)); 21 | } 22 | 23 | @Override 24 | public SkinImpl fetchInstant(Player player) { 25 | return skinCache.getFromPlayer(player); 26 | } 27 | 28 | @Override 29 | public boolean supportsInstant(Player player) { 30 | return true; 31 | } 32 | 33 | @Override 34 | public String serialize() { 35 | return "mirror"; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/skin/descriptor/NameFetchingDescriptor.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.skin.descriptor; 2 | 3 | import lol.pyr.znpcsplus.api.skin.SkinDescriptor; 4 | import lol.pyr.znpcsplus.skin.BaseSkinDescriptor; 5 | import lol.pyr.znpcsplus.skin.SkinImpl; 6 | import lol.pyr.znpcsplus.skin.cache.MojangSkinCache; 7 | import lol.pyr.znpcsplus.util.PapiUtil; 8 | import org.bukkit.entity.Player; 9 | 10 | import java.util.concurrent.CompletableFuture; 11 | 12 | public class NameFetchingDescriptor implements BaseSkinDescriptor, SkinDescriptor { 13 | private final MojangSkinCache skinCache; 14 | private final String name; 15 | 16 | public NameFetchingDescriptor(MojangSkinCache skinCache, String name) { 17 | this.skinCache = skinCache; 18 | this.name = name; 19 | } 20 | 21 | @Override 22 | public CompletableFuture fetch(Player player) { 23 | return skinCache.fetchByName(PapiUtil.set(player, name)); 24 | } 25 | 26 | @Override 27 | public SkinImpl fetchInstant(Player player) { 28 | return skinCache.getFullyCachedByName(PapiUtil.set(player, name)); 29 | } 30 | 31 | @Override 32 | public boolean supportsInstant(Player player) { 33 | return skinCache.isNameFullyCached(PapiUtil.set(player, name)); 34 | } 35 | 36 | public String getName() { 37 | return name; 38 | } 39 | 40 | @Override 41 | public String serialize() { 42 | return "fetching;" + name; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/skin/descriptor/UUIDFetchingDescriptor.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.skin.descriptor; 2 | 3 | import lol.pyr.znpcsplus.api.skin.SkinDescriptor; 4 | import lol.pyr.znpcsplus.skin.BaseSkinDescriptor; 5 | import lol.pyr.znpcsplus.skin.SkinImpl; 6 | import lol.pyr.znpcsplus.skin.cache.MojangSkinCache; 7 | import org.bukkit.entity.Player; 8 | 9 | import java.util.UUID; 10 | import java.util.concurrent.CompletableFuture; 11 | 12 | public class UUIDFetchingDescriptor implements BaseSkinDescriptor, SkinDescriptor { 13 | 14 | private final MojangSkinCache skinCache; 15 | private final UUID uuid; 16 | 17 | public UUIDFetchingDescriptor(MojangSkinCache skinCache, UUID uuid) { 18 | this.skinCache = skinCache; 19 | this.uuid = uuid; 20 | } 21 | 22 | @Override 23 | public CompletableFuture fetch(Player player) { 24 | return skinCache.fetchByUUID(uuid.toString()); 25 | } 26 | 27 | @Override 28 | public SkinImpl fetchInstant(Player player) { 29 | return fetch(player).join(); 30 | } 31 | 32 | @Override 33 | public boolean supportsInstant(Player player) { 34 | return false; 35 | } 36 | 37 | @Override 38 | public String serialize() { 39 | return "fetching-uuid;" + uuid.toString(); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/storage/NpcStorage.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.storage; 2 | 3 | import lol.pyr.znpcsplus.npc.NpcEntryImpl; 4 | 5 | import java.util.Collection; 6 | 7 | public interface NpcStorage { 8 | Collection loadNpcs(); 9 | void saveNpcs(Collection npcs); 10 | void deleteNpc(NpcEntryImpl npc); 11 | default void close() { 12 | 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/storage/database/Database.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.storage.database; 2 | 3 | import java.sql.Connection; 4 | import java.util.logging.Logger; 5 | 6 | public abstract class Database { 7 | protected final Logger logger; 8 | protected Connection connection; 9 | public Database(Logger logger){ 10 | this.logger = logger; 11 | } 12 | 13 | public abstract Connection getSQLConnection(); 14 | 15 | public abstract void load(); 16 | 17 | public abstract void close(); 18 | } 19 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/tasks/HologramRefreshTask.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.tasks; 2 | 3 | import lol.pyr.znpcsplus.hologram.HologramImpl; 4 | import lol.pyr.znpcsplus.npc.NpcEntryImpl; 5 | import lol.pyr.znpcsplus.npc.NpcRegistryImpl; 6 | import org.bukkit.scheduler.BukkitRunnable; 7 | 8 | public class HologramRefreshTask extends BukkitRunnable { 9 | private final NpcRegistryImpl npcRegistry; 10 | 11 | public HologramRefreshTask(NpcRegistryImpl npcRegistry) { 12 | this.npcRegistry = npcRegistry; 13 | } 14 | 15 | @Override 16 | public void run() { 17 | for (NpcEntryImpl entry : npcRegistry.getProcessable()) { 18 | HologramImpl hologram = entry.getNpc().getHologram(); 19 | if (hologram.shouldRefresh()) hologram.refresh(); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/tasks/ViewableHideOnLeaveListener.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.tasks; 2 | 3 | import lol.pyr.znpcsplus.util.Viewable; 4 | import org.bukkit.event.EventHandler; 5 | import org.bukkit.event.Listener; 6 | import org.bukkit.event.player.PlayerQuitEvent; 7 | 8 | public class ViewableHideOnLeaveListener implements Listener { 9 | @EventHandler 10 | public void onQuit(PlayerQuitEvent event) { 11 | Viewable.all().forEach(viewable -> { 12 | if (viewable.isVisibleTo(event.getPlayer())) viewable.UNSAFE_removeViewer(event.getPlayer()); 13 | }); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/updater/UpdateNotificationListener.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.updater; 2 | 3 | import lol.pyr.znpcsplus.ZNpcsPlus; 4 | import lol.pyr.znpcsplus.scheduling.TaskScheduler; 5 | import net.kyori.adventure.platform.bukkit.BukkitAudiences; 6 | import net.kyori.adventure.text.Component; 7 | import net.kyori.adventure.text.event.ClickEvent; 8 | import net.kyori.adventure.text.format.NamedTextColor; 9 | import org.bukkit.event.EventHandler; 10 | import org.bukkit.event.Listener; 11 | import org.bukkit.event.player.PlayerJoinEvent; 12 | 13 | public class UpdateNotificationListener implements Listener { 14 | private final ZNpcsPlus plugin; 15 | private final BukkitAudiences adventure; 16 | private final UpdateChecker updateChecker; 17 | private final TaskScheduler scheduler; 18 | 19 | public UpdateNotificationListener(ZNpcsPlus plugin, BukkitAudiences adventure, UpdateChecker updateChecker, TaskScheduler scheduler) { 20 | this.plugin = plugin; 21 | this.adventure = adventure; 22 | this.updateChecker = updateChecker; 23 | this.scheduler = scheduler; 24 | } 25 | 26 | @EventHandler 27 | public void onJoin(PlayerJoinEvent event) { 28 | if (!event.getPlayer().hasPermission("znpcsplus.updates")) return; 29 | if (updateChecker.getStatus() != UpdateChecker.Status.UPDATE_NEEDED) return; 30 | scheduler.runLaterAsync(() -> { 31 | if (!event.getPlayer().isOnline()) return; 32 | adventure.player(event.getPlayer()) 33 | .sendMessage(Component.text(plugin.getDescription().getName() + " v" + updateChecker.getLatestVersion() + " is available now!", NamedTextColor.GOLD).appendNewline() 34 | .append(Component.text("Click this message to open the Spigot page (CLICK)", NamedTextColor.YELLOW)).clickEvent(ClickEvent.openUrl(UpdateChecker.DOWNLOAD_LINK))); 35 | }, 100L); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/user/ClientPacketListener.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.user; 2 | 3 | import com.github.retrooper.packetevents.event.PacketListener; 4 | import com.github.retrooper.packetevents.event.PacketSendEvent; 5 | import com.github.retrooper.packetevents.protocol.packettype.PacketType; 6 | import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerJoinGame; 7 | import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerServerData; 8 | import lol.pyr.znpcsplus.config.ConfigManager; 9 | 10 | public class ClientPacketListener implements PacketListener { 11 | private final ConfigManager configManager; 12 | 13 | public ClientPacketListener(ConfigManager configManager) { 14 | this.configManager = configManager; 15 | } 16 | 17 | @Override 18 | public void onPacketSend(PacketSendEvent event) { 19 | if (!configManager.getConfig().fakeEnforceSecureChat()) return; 20 | if (event.getPacketType() == PacketType.Play.Server.SERVER_DATA) { 21 | WrapperPlayServerServerData packet = new WrapperPlayServerServerData(event); 22 | packet.setEnforceSecureChat(true); 23 | event.setByteBuf(packet.getBuffer()); 24 | } else if (event.getPacketType() == PacketType.Play.Server.JOIN_GAME) { 25 | WrapperPlayServerJoinGame packet = new WrapperPlayServerJoinGame(event); 26 | packet.setEnforcesSecureChat(true); 27 | event.setByteBuf(packet.getBuffer()); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/user/User.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.user; 2 | 3 | import lol.pyr.znpcsplus.api.interaction.InteractionAction; 4 | import org.bukkit.Bukkit; 5 | import org.bukkit.entity.Player; 6 | 7 | import java.util.HashMap; 8 | import java.util.Map; 9 | import java.util.UUID; 10 | 11 | public class User { 12 | private final UUID uuid; 13 | private long lastNpcInteraction; 14 | private long lastNpcKnockback; 15 | private final Map actionCooldownMap = new HashMap<>(); 16 | 17 | public User(UUID uuid) { 18 | this.uuid = uuid; 19 | } 20 | 21 | public Player getPlayer() { 22 | return Bukkit.getPlayer(uuid); 23 | } 24 | 25 | public boolean canInteract() { 26 | if (System.currentTimeMillis() - lastNpcInteraction > 100L) { 27 | lastNpcInteraction = System.currentTimeMillis(); 28 | return true; 29 | } 30 | return false; 31 | } 32 | 33 | public boolean canKnockback(int cooldown) { 34 | if (System.currentTimeMillis() - lastNpcKnockback > cooldown) { 35 | lastNpcKnockback = System.currentTimeMillis(); 36 | return true; 37 | } 38 | return false; 39 | } 40 | 41 | public UUID getUuid() { 42 | return uuid; 43 | } 44 | 45 | public boolean actionCooldownCheck(InteractionAction action) { 46 | UUID id = action.getUuid(); 47 | if (System.currentTimeMillis() - actionCooldownMap.getOrDefault(id, 0L) >= action.getCooldown()) { 48 | actionCooldownMap.put(id, System.currentTimeMillis()); 49 | return true; 50 | } 51 | return false; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/user/UserListener.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.user; 2 | 3 | import org.bukkit.event.EventHandler; 4 | import org.bukkit.event.Listener; 5 | import org.bukkit.event.player.PlayerJoinEvent; 6 | import org.bukkit.event.player.PlayerQuitEvent; 7 | 8 | public class UserListener implements Listener { 9 | private final UserManager manager; 10 | 11 | public UserListener(UserManager manager) { 12 | this.manager = manager; 13 | } 14 | 15 | @EventHandler 16 | public void onJoin(PlayerJoinEvent event) { 17 | manager.get(event.getPlayer()); 18 | } 19 | 20 | @EventHandler 21 | public void onQuit(PlayerQuitEvent event) { 22 | manager.remove(event.getPlayer().getUniqueId()); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/user/UserManager.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.user; 2 | 3 | import org.bukkit.Bukkit; 4 | import org.bukkit.entity.Player; 5 | 6 | import java.util.Map; 7 | import java.util.UUID; 8 | import java.util.concurrent.ConcurrentHashMap; 9 | 10 | public class UserManager { 11 | private final Map userMap = new ConcurrentHashMap<>(); 12 | 13 | public UserManager() { 14 | Bukkit.getOnlinePlayers().forEach(this::get); 15 | } 16 | 17 | public User get(Player player) { 18 | return get(player.getUniqueId()); 19 | } 20 | 21 | public User get(UUID uuid) { 22 | return userMap.computeIfAbsent(uuid, User::new); 23 | } 24 | 25 | public void remove(Player player) { 26 | remove(player.getUniqueId()); 27 | } 28 | 29 | public void remove(UUID uuid) { 30 | userMap.remove(uuid); 31 | } 32 | 33 | public void shutdown() { 34 | Bukkit.getOnlinePlayers().forEach(this::remove); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/util/BungeeConnector.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.util; 2 | 3 | import com.google.common.io.ByteArrayDataOutput; 4 | import com.google.common.io.ByteStreams; 5 | import org.bukkit.Bukkit; 6 | import org.bukkit.entity.Player; 7 | import org.bukkit.plugin.Plugin; 8 | 9 | public class BungeeConnector { 10 | private final static String CHANNEL_NAME = "BungeeCord"; 11 | private final Plugin plugin; 12 | 13 | public BungeeConnector(Plugin plugin) { 14 | this.plugin = plugin; 15 | } 16 | 17 | public void connectPlayer(Player player, String server) { 18 | player.sendPluginMessage(plugin, CHANNEL_NAME, createMessage("Connect", server)); 19 | } 20 | 21 | @SuppressWarnings("UnstableApiUsage") 22 | private byte[] createMessage(String... parts) { 23 | ByteArrayDataOutput out = ByteStreams.newDataOutput(); 24 | for (String part : parts) out.writeUTF(part); 25 | return out.toByteArray(); 26 | } 27 | 28 | public void registerChannel() { 29 | Bukkit.getMessenger().registerOutgoingPluginChannel(plugin, CHANNEL_NAME); 30 | } 31 | 32 | public void unregisterChannel() { 33 | Bukkit.getMessenger().unregisterOutgoingPluginChannel(plugin, CHANNEL_NAME); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/util/FileUtil.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.util; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.IOException; 5 | import java.io.Reader; 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | public class FileUtil { 10 | public static String dumpReaderAsString(Reader reader) { 11 | BufferedReader bReader = new BufferedReader(reader); 12 | try { 13 | List lines = new ArrayList<>(); 14 | String line; 15 | while ((line = bReader.readLine()) != null) { 16 | lines.add(line); 17 | } 18 | return String.join("\n", lines); 19 | } catch (IOException e) { 20 | throw new RuntimeException(e); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/util/FoliaUtil.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.util; 2 | 3 | import lol.pyr.znpcsplus.reflection.Reflections; 4 | import org.bukkit.Location; 5 | import org.bukkit.entity.Entity; 6 | 7 | import java.lang.reflect.InvocationTargetException; 8 | 9 | public class FoliaUtil { 10 | private static final Boolean FOLIA = isFolia(); 11 | public static boolean isFolia() { 12 | if (FOLIA != null) return FOLIA; 13 | try { 14 | Class.forName("io.papermc.paper.threadedregions.RegionizedServer"); 15 | return true; 16 | } catch (ClassNotFoundException e) { 17 | return false; 18 | } 19 | } 20 | 21 | public static void teleport(Entity entity, Location location) { 22 | if (!isFolia()) entity.teleport(location); 23 | else try { 24 | Reflections.FOLIA_TELEPORT_ASYNC.get().invoke(entity, location); 25 | } catch (IllegalAccessException | InvocationTargetException e) { 26 | System.err.println("Error while teleporting entity:"); 27 | e.printStackTrace(); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/util/FutureUtil.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.util; 2 | 3 | import java.util.Collection; 4 | import java.util.concurrent.CompletableFuture; 5 | import java.util.function.Supplier; 6 | 7 | public class FutureUtil { 8 | public static CompletableFuture allOf(Collection> futures) { 9 | return exceptionPrintingRunAsync(() -> { 10 | for (CompletableFuture future : futures) future.join(); 11 | }); 12 | } 13 | 14 | public static CompletableFuture newExceptionPrintingFuture() { 15 | return new CompletableFuture().exceptionally(throwable -> { 16 | throwable.printStackTrace(); 17 | return null; 18 | }); 19 | } 20 | 21 | public static CompletableFuture exceptionPrintingRunAsync(Runnable runnable) { 22 | return CompletableFuture.runAsync(runnable).exceptionally(throwable -> { 23 | throwable.printStackTrace(); 24 | return null; 25 | }); 26 | } 27 | 28 | public static CompletableFuture exceptionPrintingSupplyAsync(Supplier supplier) { 29 | return CompletableFuture.supplyAsync(supplier).exceptionally(throwable -> { 30 | throwable.printStackTrace(); 31 | return null; 32 | }); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/util/ItemSerializationUtil.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.util; 2 | 3 | import org.bukkit.inventory.ItemStack; 4 | import org.bukkit.inventory.meta.ItemMeta; 5 | import org.bukkit.util.io.BukkitObjectInputStream; 6 | import org.bukkit.util.io.BukkitObjectOutputStream; 7 | 8 | import java.io.ByteArrayInputStream; 9 | import java.io.ByteArrayOutputStream; 10 | import java.io.IOException; 11 | import java.util.Base64; 12 | 13 | public class ItemSerializationUtil { 14 | public static byte[] objectToBytes(Object obj) { 15 | ByteArrayOutputStream bout = new ByteArrayOutputStream(); 16 | try { 17 | new BukkitObjectOutputStream(bout).writeObject(obj); 18 | } catch (IOException e) { 19 | throw new RuntimeException(e); 20 | } 21 | return bout.toByteArray(); 22 | } 23 | 24 | @SuppressWarnings({"unchecked", "unused"}) 25 | public static T objectFromBytes(byte[] bytes, Class clazz) { 26 | ByteArrayInputStream bin = new ByteArrayInputStream(bytes); 27 | try { 28 | return (T) new BukkitObjectInputStream(bin).readObject(); 29 | } catch (IOException | ClassNotFoundException e) { 30 | throw new RuntimeException(e); 31 | } 32 | } 33 | 34 | public static String itemToB64(ItemStack item) { 35 | if (item == null) return null; 36 | return Base64.getEncoder().encodeToString(objectToBytes(item)); 37 | } 38 | 39 | public static ItemStack itemFromB64(String str) { 40 | if (str == null) return null; 41 | return objectFromBytes(Base64.getDecoder().decode(str), ItemStack.class); 42 | } 43 | 44 | public static ItemMeta metaFromB64(String str) { 45 | return objectFromBytes(Base64.getDecoder().decode(str), ItemMeta.class); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/util/LazyLoader.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.util; 2 | 3 | import java.util.function.Supplier; 4 | 5 | public class LazyLoader { 6 | private final Supplier supplier; 7 | private T value; 8 | 9 | private LazyLoader(Supplier supplier) { 10 | this.supplier = supplier; 11 | } 12 | 13 | public T get() { 14 | if (value == null) value = supplier.get(); 15 | return value; 16 | } 17 | 18 | public static LazyLoader of(Supplier supplier) { 19 | return new LazyLoader<>(supplier); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /plugin/src/main/java/lol/pyr/znpcsplus/util/PapiUtil.java: -------------------------------------------------------------------------------- 1 | package lol.pyr.znpcsplus.util; 2 | 3 | import me.clip.placeholderapi.PlaceholderAPI; 4 | import net.kyori.adventure.text.Component; 5 | import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; 6 | import org.bukkit.Bukkit; 7 | import org.bukkit.entity.Player; 8 | 9 | public class PapiUtil { 10 | private static boolean isSupported() { 11 | return Bukkit.getPluginManager().isPluginEnabled("PlaceholderAPI"); 12 | } 13 | 14 | public static String set(String str) { 15 | return set(null, str); 16 | } 17 | 18 | public static String set(Player player, String str) { 19 | return isSupported() ? PlaceholderAPI.setPlaceholders(player, str) : str; 20 | } 21 | 22 | // Ugly workaround would be cool if a better solution existed 23 | public static Component set(LegacyComponentSerializer serializer, Player player, Component component) { 24 | if (!isSupported()) return component; 25 | return serializer.deserialize(set(player, serializer.serialize(component))); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /plugin/src/main/resources/messages/action-hover/add.txt: -------------------------------------------------------------------------------- 1 | Examples: 2 | * /npc action add consolecommand cool_npc1 ANY_CLICK 0 0 say {player} just clicked a cool npc! 3 | * /npc action add playerchat dog LEFT_CLICK 0 100 It has been 5 seconds since i clicked the npc 4 | * /npc action add message npc123 RIGHT_CLICK 1 0 You can only click this npc once per second 5 | 6 | Action Types: 7 | * Console Command - Send a console command when a player interacts with the npc 8 | * Message - Send a message to any player that interacts with the npc 9 | * Player Chat - Make any player that interacts send something in the chat 10 | * Player Command - Make any player that interacts send a command 11 | * Switch Server - Send the player to a different server on the proxy using bungee messaging channel 12 | 13 | Command used to add actions to an npc -------------------------------------------------------------------------------- /plugin/src/main/resources/messages/action-hover/clear.txt: -------------------------------------------------------------------------------- 1 | Usage » /npc action clear 2 | 3 | Command used to clear all npc actions -------------------------------------------------------------------------------- /plugin/src/main/resources/messages/action-hover/delete.txt: -------------------------------------------------------------------------------- 1 | Usage » /npc action delete 2 | 3 | Command used to delete a specific action from an npc -------------------------------------------------------------------------------- /plugin/src/main/resources/messages/action-hover/edit.txt: -------------------------------------------------------------------------------- 1 | Usage » /npc action edit 2 | 3 | Command used to change a specific action on an npc -------------------------------------------------------------------------------- /plugin/src/main/resources/messages/action-hover/list.txt: -------------------------------------------------------------------------------- 1 | Usage » /npc action list 2 | 3 | Command used to list all actions of an npc -------------------------------------------------------------------------------- /plugin/src/main/resources/messages/action.txt: -------------------------------------------------------------------------------- 1 | 2 | ZNPCsPlus v${version} Click to view the main help message'>[BACK] 3 | Hover over any command for more info 4 | 5 | * /npc action add 6 | * /npc action clear 7 | * /npc action delete 8 | * /npc action edit 9 | * /npc action list 10 | 11 | -------------------------------------------------------------------------------- /plugin/src/main/resources/messages/holo-hover/add.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pyrbu/ZNPCsPlus/63db907d325730e73367de4ce17133df2697ba76/plugin/src/main/resources/messages/holo-hover/add.txt -------------------------------------------------------------------------------- /plugin/src/main/resources/messages/holo-hover/additem.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pyrbu/ZNPCsPlus/63db907d325730e73367de4ce17133df2697ba76/plugin/src/main/resources/messages/holo-hover/additem.txt -------------------------------------------------------------------------------- /plugin/src/main/resources/messages/holo-hover/delete.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pyrbu/ZNPCsPlus/63db907d325730e73367de4ce17133df2697ba76/plugin/src/main/resources/messages/holo-hover/delete.txt -------------------------------------------------------------------------------- /plugin/src/main/resources/messages/holo-hover/info.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pyrbu/ZNPCsPlus/63db907d325730e73367de4ce17133df2697ba76/plugin/src/main/resources/messages/holo-hover/info.txt -------------------------------------------------------------------------------- /plugin/src/main/resources/messages/holo-hover/insert.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pyrbu/ZNPCsPlus/63db907d325730e73367de4ce17133df2697ba76/plugin/src/main/resources/messages/holo-hover/insert.txt -------------------------------------------------------------------------------- /plugin/src/main/resources/messages/holo-hover/insertitem.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pyrbu/ZNPCsPlus/63db907d325730e73367de4ce17133df2697ba76/plugin/src/main/resources/messages/holo-hover/insertitem.txt -------------------------------------------------------------------------------- /plugin/src/main/resources/messages/holo-hover/offset.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pyrbu/ZNPCsPlus/63db907d325730e73367de4ce17133df2697ba76/plugin/src/main/resources/messages/holo-hover/offset.txt -------------------------------------------------------------------------------- /plugin/src/main/resources/messages/holo-hover/refreshdelay.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pyrbu/ZNPCsPlus/63db907d325730e73367de4ce17133df2697ba76/plugin/src/main/resources/messages/holo-hover/refreshdelay.txt -------------------------------------------------------------------------------- /plugin/src/main/resources/messages/holo-hover/set.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pyrbu/ZNPCsPlus/63db907d325730e73367de4ce17133df2697ba76/plugin/src/main/resources/messages/holo-hover/set.txt -------------------------------------------------------------------------------- /plugin/src/main/resources/messages/holo-hover/setitem.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pyrbu/ZNPCsPlus/63db907d325730e73367de4ce17133df2697ba76/plugin/src/main/resources/messages/holo-hover/setitem.txt -------------------------------------------------------------------------------- /plugin/src/main/resources/messages/holo.txt: -------------------------------------------------------------------------------- 1 | 2 | ZNPCsPlus v${version} Click to view the main help message'>[BACK] 3 | Hover over any command more info 4 | 5 | * /npc holo add 6 | * /npc holo set 7 | * /npc holo insert 8 | 9 | * /npc holo additem 10 | * /npc holo setitem 11 | * /npc holo insertitem 12 | 13 | * /npc holo delete 14 | 15 | * /npc holo offset 16 | * /npc holo refreshdelay 17 | * /npc holo info 18 | 19 | -------------------------------------------------------------------------------- /plugin/src/main/resources/messages/property-hover/remove.txt: -------------------------------------------------------------------------------- 1 | Usage » /npc property remove 2 | 3 | Command used to unset properties on npcs -------------------------------------------------------------------------------- /plugin/src/main/resources/messages/property-hover/set.txt: -------------------------------------------------------------------------------- 1 | Usage » /npc property set 2 | 3 | Command used to customize npcs with custom properties -------------------------------------------------------------------------------- /plugin/src/main/resources/messages/property.txt: -------------------------------------------------------------------------------- 1 | 2 | ZNPCsPlus v${version} Click to view the main help message'>[BACK] 3 | Hover over any command more info 4 | 5 | * /npc property set 6 | * /npc property remove 7 | 8 | -------------------------------------------------------------------------------- /plugin/src/main/resources/messages/root-hover/center.txt: -------------------------------------------------------------------------------- 1 | Usage » /npc center 2 | 3 | Command used to move an npc to the center of the block it''s currently occupying -------------------------------------------------------------------------------- /plugin/src/main/resources/messages/root-hover/changeid.txt: -------------------------------------------------------------------------------- 1 | Usage » /npc changeid 2 | 3 | Command used to change the id of an npc -------------------------------------------------------------------------------- /plugin/src/main/resources/messages/root-hover/create.txt: -------------------------------------------------------------------------------- 1 | Usage » /npc create 2 | 3 | Command used to create an npc of a given type -------------------------------------------------------------------------------- /plugin/src/main/resources/messages/root-hover/delete.txt: -------------------------------------------------------------------------------- 1 | Usage » /npc delete 2 | 3 | Command used to delete an npc -------------------------------------------------------------------------------- /plugin/src/main/resources/messages/root-hover/list.txt: -------------------------------------------------------------------------------- 1 | Usage » /npc list 2 | 3 | Command used to list all npcs -------------------------------------------------------------------------------- /plugin/src/main/resources/messages/root-hover/lookatme.txt: -------------------------------------------------------------------------------- 1 | Usage » /npc lookatme 2 | 3 | Command used to set the rotation of an npc to be looking at your current location -------------------------------------------------------------------------------- /plugin/src/main/resources/messages/root-hover/move.txt: -------------------------------------------------------------------------------- 1 | Usage » /npc move 2 | 3 | Command used to set the location of an npc to your current location -------------------------------------------------------------------------------- /plugin/src/main/resources/messages/root-hover/near.txt: -------------------------------------------------------------------------------- 1 | Usage » /npc near 2 | 3 | Command used to check which npcs are within a given radius around you -------------------------------------------------------------------------------- /plugin/src/main/resources/messages/root-hover/setlocation.txt: -------------------------------------------------------------------------------- 1 | Usage » /npc setlocation 2 | 3 | Command used to manually adjust an npc''s location -------------------------------------------------------------------------------- /plugin/src/main/resources/messages/root-hover/setrotation.txt: -------------------------------------------------------------------------------- 1 | Usage » /npc setrotation 2 | 3 | Command used to manually adjust an npc''s rotation -------------------------------------------------------------------------------- /plugin/src/main/resources/messages/root-hover/skin.txt: -------------------------------------------------------------------------------- 1 | Examples: 2 | * /npc skin cool_npc1 static Notch 3 | * /npc skin my_npc mirror 4 | * /npc skin 12 dynamic %leaderboard_mining_top_1% 5 | * /npc skin npc1234 url classic https://s.namemc.com/i/5d5eb6d84b57ea29.png 6 | 7 | Skin Types: 8 | * Static - Only fetch the skin once and save the skin data 9 | * Mirror - Copy the skin of the player who is viewing the npc 10 | * Dynamic - Fetch the skin whenever the npc comes into viewing distance (supports placeholders) 11 | * Url - Fetch the skin from an url to a raw skin file, this works like static 12 | 13 | Command used to change the skin of an npc -------------------------------------------------------------------------------- /plugin/src/main/resources/messages/root-hover/teleport.txt: -------------------------------------------------------------------------------- 1 | Usage » /npc teleport 2 | 3 | Command used to teleport yourself to an npc -------------------------------------------------------------------------------- /plugin/src/main/resources/messages/root-hover/toggle.txt: -------------------------------------------------------------------------------- 1 | Usage » /npc toggle 2 | 3 | Command used to enable or disable an npc -------------------------------------------------------------------------------- /plugin/src/main/resources/messages/root-hover/type.txt: -------------------------------------------------------------------------------- 1 | Usage » /npc type 2 | 3 | Command used to change the type of an npc -------------------------------------------------------------------------------- /plugin/src/main/resources/messages/root.txt: -------------------------------------------------------------------------------- 1 | 2 | ZNPCsPlus v${version} 3 | Hover over any command for more info 4 | 5 | * /npc create 6 | * /npc delete 7 | * /npc changeid 8 | * /npc toggle 9 | * /npc list 10 | * /npc type 11 | 12 | * /npc near 13 | * /npc center 14 | * /npc lookatme 15 | * /npc setlocation 16 | * /npc setrotation 17 | * /npc move 18 | * /npc teleport 19 | 20 | * /npc skin 21 | 22 | * Npc property commands
Click to view full list'>/npc property help 23 | * Npc hologram commands
Click to view full list'>/npc holo help 24 | * Player interaction commands
Click to view full list'>/npc action help 25 | * Npc data storage commands
Click to view full list'>/npc storage help 26 | 27 | -------------------------------------------------------------------------------- /plugin/src/main/resources/messages/storage-hover/import.txt: -------------------------------------------------------------------------------- 1 | Usage » /npc storage import 2 | 3 | Importers: 4 | * znpcs - Imports npcs from the ZNPCs plugin 5 | * znpcsplus_legacy - Imports npcs from legacy versions of ZNPCsPlus 6 | * citizens - Imports npcs from the Citizens plugin 7 | 8 | Command used to import npcs from a different source -------------------------------------------------------------------------------- /plugin/src/main/resources/messages/storage-hover/migrate.txt: -------------------------------------------------------------------------------- 1 | Usage » /npc storage migrate [force] 2 | 3 | Storage Types: 4 | * YAML - Npcs are stored in yaml files 5 | * SQLite - Npcs are stored in a SQLite database 6 | * MySQL - Npcs are stored in a MySQL database 7 | 8 | Command used to migrate npcs from one storage type to another. 9 | 10 | This command will NOT delete the original storage files or database, 11 | but will copy the npcs to the new storage type. 12 | 13 | This will also not overwrite any existing npcs in the new storage 14 | type, unless the force argument is set to true. 15 | Warning: force will overwrite any existing npcs with the same id 16 | in the new storage type and CANNOT be undone. -------------------------------------------------------------------------------- /plugin/src/main/resources/messages/storage-hover/reload.txt: -------------------------------------------------------------------------------- 1 | Usage » /npc storage reload 2 | 3 | Command used to re-load all npcs from storage 4 | Warning: This command will delete all unsaved changes to npcs -------------------------------------------------------------------------------- /plugin/src/main/resources/messages/storage-hover/save.txt: -------------------------------------------------------------------------------- 1 | Usage » /npc storage save 2 | 3 | Command used to save the currently loaded npcs to storage -------------------------------------------------------------------------------- /plugin/src/main/resources/messages/storage.txt: -------------------------------------------------------------------------------- 1 | 2 | ZNPCsPlus v${version} Click to view the main help message'>[BACK] 3 | Hover over any command for more info 4 | 5 | * /npc storage save 6 | * /npc storage reload 7 | * /npc storage import 8 | * /npc storage migrate [force] 9 | 10 | -------------------------------------------------------------------------------- /plugin/src/main/resources/plugin.yml: -------------------------------------------------------------------------------- 1 | name: ZNPCsPlus 2 | authors: 3 | - Pyr 4 | - D3v1s0m 5 | 6 | main: lol.pyr.znpcsplus.ZNpcsPlusBootstrap 7 | load: POSTWORLD 8 | 9 | version: ${version} 10 | api-version: 1.13 11 | 12 | folia-supported: true 13 | 14 | softdepend: 15 | - PlaceholderAPI 16 | - ServersNPC 17 | - ProtocolLib 18 | - ProtocolSupport 19 | - ViaVersion 20 | - ViaBackwards 21 | - ViaRewind 22 | - Geyser-Spigot 23 | 24 | loadbefore: 25 | - Quests 26 | 27 | commands: 28 | npc: 29 | aliases: 30 | - znpc 31 | - znpcs 32 | - npcs 33 | permission: znpcsplus.command.npc 34 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = "ZNPCsPlus" 2 | 3 | include "api", "plugin" --------------------------------------------------------------------------------