
Vanilla Core
A comprehensive all-in-one SMP plugin for PvP balance, custom mechanics, and server management. (Alternative to SMP Core)
Vanilla Core 1.4.1
release18 марта 2026 г.[1.4.1] - 2026-03-19
Fixed
- : replaced console dispatch with direct delivery so Xaero control strings are sent as chat text without Brigadier JSON parsing errors during GUI clicks
Security
- All plugin GUIs now use (a typed ) as the inventory holder instead of ; click and close dispatch in and all individual feature listeners now identify plugin GUIs by holder type rather than title string, preventing spoofed inventory titles from triggering plugin GUI handlers
- : added handler that cancels any drag action into plugin GUIs (covers -backed inventories and )
Vanilla Core 1.4.0
release7 марта 2026 г.Fixed
VanillaCorePlugin: removed duplicate"vanillacore"entries in the data-folder migration array (was listed three times)VanillaCorePlugin: re-added"SMPCore"legacy alias to data-folder migration array so configs from that legacy folder name are migrated correctlyConfigManager: corrected default config keyfeatures.mace-limiter.mace-crafted→features.mace-limiter.maces-craftedso config migration properly seeds the mace craft counterConfigManager: added explicit migration step to remove the old booleanmace-craftedkey and convert its value to the new integermaces-craftedkey in existing configsConfigManager: fixed migration log message reporting total defaults instead of actually-added entry count; also removed dead empty features arrayConfigManager: bumpedCURRENT_CONFIG_VERSIONto 3 to reflect the newfeatures.stop-item-despawnconfig sectionDimensionLockFeature.toggle(): CDN-sourced messages are now escaped withMiniMessage.escapeTags()before being passed toMessageManager.parse()to prevent MiniMessage tag injection from remote payloads; also added null checks on CDN message gettersDimensionLockFeature: madesharedListenerand registration flag static soNetherLockFeatureandEndLockFeatureshare oneDimensionLockListenerinstance instead of each registering their own, preventing everyPlayerPortalEventfrom firing twiceDimensionLockFeature.toggle(): added remote-disable and maintenance-mode checks (matchingBaseFeature.toggleDefault()) before processing the toggleFeatureManager.getClasses(): removed// Skip classes that can't be loadedcomments from both catch blocks (production code no-comment rule); also added null check fordirectory.listFiles()return valueOnePlayerSleepListener: player name and display name are now escaped withMiniMessage.escapeTags()before substitution to prevent tag injection; sleep message is parsed once and reused for all recipients; skip message is also parsed once outside the loopOnePlayerSleepListener: sleep and skip messages now parsed throughMessageManager.parse()so MiniMessage tags (e.g.<yellow>{player}) render correctly instead of showing literallyMaceLimiterListener: shift-click mace crafting now validates cursor is empty and inventory has space before consuming ingredients; result is added viaaddItem()instead ofsetItemOnCursor()to properly handle shift-click semanticsMaceLimiterListener: shift-click mace crafting now sets matrix slots tonullinstead ofsetAmount(0)when an ingredient stack reaches zero, preventing ghost items in the crafting gridServerRestartFeature:setScheduledRestartsEnabled(false)now cancels the running checker task, preventing it from continuing after scheduled restarts are disabledServerRestartFeature:startScheduledRestartChecker()now stores its task ID;reload()andonDisable()cancel the old checker task before starting a new one, preventing accumulated duplicate restart-checker tasks across reloadsStopItemDespawnListener: double-death within 60-tick window no longer causes the second death location to be prematurely removed; previous cleanup task is cancelled before scheduling a new oneStopItemDespawnListener: stale UUID accumulation fixed —onItemDespawnnow always removes item UUID fromdeathDropseven when feature is disabled, preventing unbounded set growth for items destroyed by lava/void/explosionsStopItemDespawnListener: proximity radius check changed from< 16to<= 16so items spawning exactly 4 blocks from the death location are includedStopItemDespawnListener:onItemMergenow checksisEnabled()to avoid silently transferring tags when feature is toggled off mid-sessionMenuClickListener: ARROW back-button click in Mob Manager World Select GUI now also validates the slot (inventorySize - 3) to prevent any future ARROW item from accidentally triggering navigationFeatureManager.getClasses(): added null check fordirectory.listFiles()return value to preventNullPointerExceptionwhen an I/O error occurs in dev/directory modeInvisibleKillsFeature: standardised default death-message fallback tag from<obfuscated>to<obf>to match the default inInvisibleKillsListenerMinimapControlFeature.sendTellraw(): switched from player name to UUID when targeting thetellrawcommand to be future-proof against edge casesNetheriteDisablerListener:event.getView().getPlayer()guarded withinstanceof Playerpattern-match to prevent aClassCastExceptionif a non-player human entity ever triggers the smithing event
Added
- Stop Item Despawn feature: items dropped when a player dies will never despawn naturally; they persist indefinitely until picked up; enabled via
features.stop-item-despawn.enabled - Back button (ARROW) to Shield Mechanics settings GUI (slot 22) to navigate back to the main menu
- Back button (ARROW) to Mob Manager World Select GUI (slot
size-3) to navigate back to the main menu
Changed
-
VanillaCorePlugin: scheduledCooldownManager.cleanup()as an async repeating task (every 5 minutes) to evict expired cooldown entries for offline players and prevent unbounded memory growth -
CDNManager: removed the unusedCachedDatainner class -
ChatInputListener: migrated from deprecatedAsyncPlayerChatEvent(Bukkit) toAsyncChatEvent(Paper) andPlainTextComponentSerializerfor message extraction -
Breach Swap: swapping between a Breach-enchanted mace and a sword/axe is now allowed freely; the first attack within 500ms of that swap is blocked instead, removing the attribute-swap PvP advantage without restricting movement
-
Breach Swap GUI: the mace icon in the settings menu now displays with an enchantment glint
Vanilla Core 1.3.3
release1 марта 2026 г.Changed
- Migrated all player messaging from legacy §-code strings to Adventure API (
Component/MiniMessage) across all command and listener classes - Migrated
UpdateNotificationListenerfrom BungeeCord chat API to Adventure API (ClickEvent,HoverEvent,Componentbuilder) - Fixed
InfiniteRestockFeatureblacklist GUI:statusText/statusColornow use MiniMessage tags (<red>,<green>) instead of §-codes so they render correctly when passed toMessageManager.parse() - Item Limiter:
findMatchingItemKeyno longer scans all configured limits linearly. AMaterial → keyindex is built at load time so lookups are O(1) for the common case instead of O(n limits) - Item Limiter: inventory scan is now distributed across ticks (1 player per tick) instead of checking every online player in a single 20-tick burst
- Item Limiter:
getPlayerItemCountno longer re-runsfindMatchingItemKeyfor each inventory slot — the target limit is resolved once andItemLimit.matches()is used directly - Item Limiter: potion material detection replaced
toString().contains("POTION")with a properEnumSet<Material>coveringPOTION,SPLASH_POTION, andLINGERING_POTION - Completed Adventure API migration: replaced all remaining legacy § color codes in
ServerRestartFeature,ShieldMechanicsFeature,MinimapControlFeature,ItemLimiterListener,MaceLimiterListener,InvisibleKillsFeature, andMainMenuwith MiniMessage format; GUI title constants inMaceLimiterFeature,ShieldMechanicsFeature,MobManagerFeature, andServerRestartFeatureconverted from §-coded strings toComponentconstants; corresponding listeners updated to useInventoryView.title()(Component API) for title matching ServerRestartFeature: migrated from BungeeCord ActionBar API and Bukkit BossBar to Adventure API (player.sendActionBar,player.showTitle,net.kyori.adventure.bossbar.BossBar)MainMenu: replaced deprecatedgetLore()+ §-detection withlore()+PlainTextComponentSerializerfor lore inspectionconfig.yml: migrated all message values from § codes to MiniMessage format- Added JUnit 5 (
junit-jupiter:5.10.0) as a test dependency ServerRestartListener: replaced non-thread-safeHashMapwithConcurrentHashMapforawaitingInput; async chat handler now uses atomicremove-and-null-check pattern to eliminate TOCTOU raceUpdateNotificationListener: CDN-provided title and message text is now escaped withMiniMessage.escapeTags()before parsing to prevent tag injectionMinimapControlFeature: world name, environment, and minimap mode values are escaped withMiniMessage.escapeTags()before being embedded in MiniMessage stringsMessageManager.get(String, Object...): now throwsIllegalArgumentExceptionimmediately when an odd number of replacement arguments is supplied or a key isnull, instead of silently ignoring the trailing argumentShieldMechanicsFeature: extracted shared stun-lore assembly intobuildStunLore(boolean, int)helper to eliminate duplication betweenbuildMaceStunItemandbuildAxeStunItemServerRestartFeature.getRestartMessage: consolidated{time}and{player}substitution into a single overloaded method; callers no longer chain.replace("{player}", ...)at the call siteMobManagerFeature.onRightClick: disabled warning now uses the centralizedmob-manager.feature-disabledmessages.yml key instead of a hardcoded literalInfiniteRestockFeature,ItemLimiterFeature:fillBordernow usesmeta.displayName(Component.empty())instead of the deprecatedmeta.setDisplayName(" ")messages.yml: removed UTF-8 BOM from file header
Fixed
VanillaCommandreload: each feature'sreload()is now wrapped in its owntry/catch; a failure in one feature no longer aborts the reload loop for all subsequent featuresMainMenu: removed unreachable duplicate slot-50 handler that could never be reached after the earlier slot-50 Wiki handler returnedMainMenu: removed duplicateimport net.kyori.adventure.text.Componentimport
Added
- Fixed
DimensionLockConfigdefaultlockedMessagevalues to use MiniMessage (<red>The End/Nether is currently locked!) - Fixed
InvisibleKillsConfigdefaultdeathMessageto use MiniMessage ({victim} was killed by <obfuscated>?????????) - Documentation: updated all
§-coded examples indocs/docs/configuration.mdto MiniMessage format
Vanilla Core 1.3.2
release27 февраля 2026 г.Added
- Shield Mechanics feature: configurable shield stun when a player is hit while blocking
- Mace hitting a blocking player puts their shield on cooldown
- Axe hitting a blocking player puts their shield on cooldown
- Stun duration adjustable per weapon type (in ticks) via GUI
- All settings accessible via /vanilla menu → Shield Mechanics → Right Click
Fixed
- Enchantment Limiter config GUI: clicking an enchantment on page 2+ would apply the action to the enchantment at the same slot on page 1 instead. Caused by firing synchronously, which wiped the stored page number before the new page was written. The page is now recorded after the inventory opens. Rare in practice — only affects servers with enough custom enchantments (from datapacks or other plugins) to fill more than 45 slots
Vanilla Core 1.3.1
release26 февраля 2026 г.Fixed
- Enchantment Limiter event handlers (enchanting table, anvil, pickup) no longer run when the feature is disabled in config
- Players who disconnect while the Enchantment Limiter config GUI is open no longer leave stale session data server-side
- Removed leftover
PrepareAnvilEventhandler that was unused - Villager discounts from curing zombie villagers and from the Hero of the Village effect now apply correctly. The old code was rebuilding
MerchantRecipeobjects from scratch on every interaction, which dropped any price multiplier changes Minecraft had set. Recipes are now modified in-place instead
Changed
- Default enchantment limits raised closer to vanilla max levels:
- Sharpness and Power: 4 → 5
- Protection, Fire Protection, Blast Protection, Projectile Protection, Feather Falling: 3 → 4
- Unbreaking: 2 → 3
- Main command class renamed from
SmpCommandtoVanillaCommand
Added
- GitHub Actions workflow that publishes to Modrinth automatically when a GitHub release is published. It builds from source, pulls the changelog for that version, and uploads via
mc-publish - PR labeler config updated to
actions/labeler@v5syntax
