SingularityLib (io.github.pinont:singularitylib) is the core framework of the Singularity Project — a Minecraft plugin development library for PaperMC. Sibling repos:
| Repo | Role |
|---|---|
| SingularityLib (this repo) | Core API library: commands, config, GUI, items, entities, auto-registration, MySQL, Discord JDA bootstrap |
SingularityPlugin |
Starter template plugin consuming SingularityLib |
Singularity-DevTool |
In-game debugging/admin tool built on SingularityLib |
Published to GitHub Packages only (https://maven.pkg.github.com/pinont/SingularityLib). JitPack is no longer part of the build.
- Modernization work lives on
rework/v2(v2 platform/toolchain pass: Paper 26.2+, JDK 25, Folia flag, GitHub Packages). Never push directly tomain; merge via PR when a pass is complete.
export JAVA_HOME=$(echo ~/dev-tools/jdk-*)
~/dev-tools/apache-maven-3.9.16/bin/mvn clean package # jar + sources + javadoc into target/
~/dev-tools/apache-maven-3.9.16/bin/mvn test # JUnit + MockBukkit- Requires JDK 25 (
<java.version>25</java.version>). - Targets Paper API 26.2+ latest-only:
paperapi.versionis the range[26.2.build,), which resolves to the newest build on repo.papermc.io at build time. The standalonefolia-apidep stays pinned at its last line26.2.build.7-beta(from Paper 26.x the Folia schedulers ship inside paper-api). - Tests run against MockBukkit
mockbukkit-v26.2(the oldmockbukkit-v1.21artifact cannot load 26.x APIs). - Shaded deps include
org.reflections(used by the deprecated auto-register fallback only), behind the-Dshadeprofile.org.reflectionsis marked<optional>true</optional>so it never leaks into consumers. - The
singularitylib-processorsubmodule (own pom, coordinatesio.github.pinont:singularitylib-processor, Java 25, zero deps) is a reactor member of the root pom: it generatesMETA-INF/singularitylib/auto-register-index.propertiesduring compilation. The root pom references it viaannotationProcessorPathsand aprovideddependency so the lib's own@AutoRegisterclasses (e.g.EntityDamageListener) are indexed too.
Root package: io.github.pinont.singularitylib
api/Plugin.java— Bukkit plugin entry point (declared insrc/main/resources/paper-plugin.yml,load: STARTUP)api/annotation/AutoRegister.java— marks classes for automatic registrationapi/command/SimpleCommand.java— simplified command abstractionapi/entity/EntityCreator.java— entity configuration/storage helpersapi/enums/—AttributeType,PersisDataType(sic — typo of PersistentDataType),PlayerInventorySlotTypeapi/event/— custom events:ItemExecuteEvent,PlayerDamageByPlayerEventapi/hook/discordJDA/— Discord bootstrap:DiscordApp,SimpleSlashCommands,SlashCommandComponent,Readyapi/items/—CustomItem,ItemCreator,ItemHeadCreator,CrossbowCreator,ItemInteractionapi/manager/—CommandManager,ConfigManager,CustomItemManager,FileManager,WorldManagerapi/runnable/—Runner,Schedulertask wrappers. Tick semantics: delay/period are server ticks on both Paper and Folia paths (FoliarunAtFixedRateand BukkitrunTaskTimerare tick-native); the only exception isrunRepeatingTaskAsync, whose delay/period follow the suppliedTimeUnit. Folia region-scheduler tasks have no bulk cancel API — cancel them via task handles/cancelTask();cancelAllTasks()covers async + global-region (Folia) or everything (Paper).api/ui/— GUI toolkit:Menu,Button,Layoutapi/utils/—Common,Console,MySQLplugin/CorePlugin.java— the contract: consumer main classes extend this instead ofJavaPlugin; overrides areonPluginStart()/onPluginStop(). Owns staticinstance, prefix, Folia detection, registration wiring. The lib itself is a bootstrap plugin declared insrc/main/resources/paper-plugin.yml(api-version: '26.2',folia-supported: true,load: STARTUP).plugin/listener/— internal listeners (EntityDamageListener,PlayerListener) backing item interaction & PvP eventsplugin/register/Register.java— auto-registration coordinator. Primary path:loadFromIndex()reads everyMETA-INF/singularitylib/auto-register-index.propertieson the classpath (compile-time index fromsingularitylib-processor), instantiates each listed class and classifies intoSimpleCommand/CustomItem/Listener. Fallback: deprecatedscanAndCollect(package)uses Reflections for legacy jars without an index. Cross-plugin dedupe viaALREADY_INSTANTIATED(first plugin wins — the lib is a bootstrap plugin withjoin-classpath: true, so shared classes must not double-register);resetDedupe()exists for tests.
Tests live in src/test/java (CorePluginTest, CommonTest, ItemCreatorMetaTest, TestPlugin). Coverage is minimal — don't assume green tests mean full safety.
- Plain Java (no Kotlin anywhere in this repo).
- Public API classes get full Javadoc — keep that up when editing them (javadoc jar is built via maven-javadoc-plugin).
- Version bumps happen through release tags;
-SNAPSHOTbetween releases.
- Version history:
pom.xmlis now2.0.0-SNAPSHOT(v2 line); tags stop at1.3.3whileRELEASE_NOTES.mddescribes a "2.2.0" initial release. Reconcile release notes before tagging v2. - Legacy color API:
org.bukkit.ChatColorused acrossConsole,Register, etc. — deprecated in modern Paper (use AdventureComponent/NamedTextColor). - Typo'd enum
PersisDataType— public API surface, renaming is breaking. Reflections scanner (resolved:Register) is startup-slow and fragile under complex classpaths/relocation@AutoRegisternow uses a compile-time index from thesingularitylib-processorannotation processor (seeplugin/register/Register.java), with the Reflections scan kept only as a deprecated fallback for legacy jars.- Ships as a plugin AND a library:
paper-plugin.ymlmakes the lib itself a plugin (main: ...api.Plugin). Consumers instead depend on it as a Maven dep and extendCorePlugin. This dual role is a design smell worth revisiting during the rework. JitPack coordinates mismatchresolved onrework/v2: the JitPack repo and the last JitPack-hosted dependency (com.github.Pinont:Singularity-DevTool) were removed from the pom. README still shows a JitPack badge/install snippet — update docs when GitHub Packages publishing goes live.- Minimal tests; no CI matrix across MC versions.
- Do not break
CorePlugin's public contract (onPluginStart/onPluginStop,getConfigManager, static accessors) — both sibling repos and unknown external plugins depend on it. - Treat all classes under
api/as public API; check downstream consumers (sibling repos, GitHub Packages) before renaming/moving anything. - New features go in the matching
api/subpackage with Javadoc; wire global behavior throughCorePlugin/Register, not static singletons where avoidable. - When touching items/events, remember the internal listeners in
plugin/listenerare the machinery behind the public events. - The owner plans a major rework: LTS/rolling MC version support, wiki + javadoc site. Favor changes that reduce coupling to a single Paper version (e.g., isolate NMS/version-specific code) over quick hacks.