Update Changelogs authored by Ashijin's avatar Ashijin
2.2.0 [[_TOC_]]
=====
- Added `Item Augments` # 5.12.0
- Big `Lore Template` improvements
Highlights
2.1.0 ----------
===== - Rewrote resource pack generation for modern item model definitions, overlays, paintings, sounds, fonts, tooltips, and deployment.
- Updated to Java 21 - Added custom equippable slots with custom menu support.
- Added a bunch of new feature features - Added inventory interaction triggers for place, take, move, and drag/drop workflows.
- Rewrote custom block system - Added connectable furniture, furniture occlusion culling, and WorldEdit furniture copy/paste support.
- Added support for tripwire hooks and chorus plants as custom blocks - Added random tick skills for custom blocks and furniture.
- Added a bunch of new API stuff - Added Paper `26.1.x` support, Java 25 server compatibility work, and 1.21.11 pack format handling.
- Fixed a trillion bugs
General
2.0.0 -------
===== - Converted the project from Maven to Gradle.
- Updated the plugin to `api-version: 1.21`.
Because of the size of this update, this changelog only includes a brief overview. More information is available throughout the wiki. - Marked the plugin as Folia-supported.
- Added automatic merging of new Crucible config defaults into existing Mythic config files.
- Added `Pack Generation` - You can now auto-generate countless things into a tidy pack - items, blocks, furniture, spell effects/bullets, unicode images, sounds, and more. We've gone above and beyond to support any format for this - including just throwing the .bbmodel file in just like MEG (the recommended method). Not only that, but there are many options to edit the item during generation, such as mutating the color to make variants. - Moved old Crucible config values into Mythic's current `config-items.yml` and `config-generation.yml` layout.
- Added `Custom Armor` - Added the ability to add custom armor without shaders. Sacrificing 1 armor type (such as chainmail) opens the door to unlimited custom armor types via trims. - Added `files/` folder support for lore templates, fonts, worldgen, equipment sets, tooltips, and augments.
- Added `Item Stats` - Items fully support the entire Mythic stat system. Did you know Mythic comes with tons of custom stats, like the good oldies such as Critical Strike? Or that you can make your own custom stats in highly flexible ways? Mythic item stats are fully compatible with stats on mobs, auras, RPG, and everything in our ecosystem - the ability to have cross-system interactions is here. - Added support for Minecraft 1.21.11 resource-pack and datapack formats.
- Added `Crafting Conditions & Skills` - Crafts now support Mythic conditions and skills! - Added initial Paper `26.1.x` compatibility work for Java 25 servers.
- Added `Lore Templates` - Creating templates for your lore that use placeholders, so you can keep a consistent look across your custom items! - Re-enabled bStats.
- Added `NBT Mechanics & Conditions` - Self explanatory - Cleaned up older pre-1.21 code paths and removed the old pre-1.21 crafting module.
- Added `Hats` - Hats!
- Added `Paint Brush` item type Resource Pack Generation
------------------------
Older Changelogs
================ ### NEW: Pack Generation Rewrite
- [1.6.X Changelogs](/1.6.x_changelogs) - Reworked the generator into smaller dedicated generators for item models, legacy overrides, pack merges, sounds, fonts, tooltips, textures, paintings, and missing texture patching.
- [1.5.X Changelogs](/1.5.x_changelogs) - Added safer generation sessions and clearer generation error logging.
- [1.4.X Changelogs](/1.4.x_changelogs) - Added per-pack and per-item generation namespaces.
- [1.3.X Changelogs](/1.3.x_changelogs)
- [1.2.X Changelogs](/1.2.x_changelogs) ```yaml
- [1.1.X Changelogs](/1.1.x_changelogs) SomeItem:
- [1.0.X Changelogs](/1.0.x_changelogs) Material: DIAMOND_SWORD
Generation:
Namespace: cosmetics
Model: item/ruby_blade
Texture: item/ruby_blade
```
### NEW: PackSquash Integration
- Added optional PackSquash support for optimizing generated zipped packs.
```yaml
Generation:
PackSquash:
Enabled: true
ExecutablePath: plugins/MythicCrucible/generation/packsquash/packsquash
SettingsPath: plugins/MythicCrucible/generation/packsquash/packsquash.toml
CacheSize: 5
```
### NEW: MCPacks Deployment
- Added `MCPACKS` as a resource pack deployment type.
- Deployment can now return the uploaded pack URL and SHA1 from MCPacks automatically.
```yaml
Generation:
Deployment:
Enabled: true
Type: MCPACKS
AutoSend:
Enabled: true
SendOnUpdate: true
Force: false
```
### NEW: Paper Configuration-Phase Pack Sending
- Added `DuringConfiguration` for sending packs during Paper's configuration phase on supported versions.
```yaml
Generation:
Deployment:
AutoSend:
Enabled: true
DuringConfiguration: true
```
### NEW: Overlay Exclusions
- Pack overlays are generated for supported versions by default.
- Added `ExcludeOverlays` to opt out of exact versions or ranges.
```yaml
Generation:
ExcludeOverlays:
- "< 1.21.4"
- ">= 26.1"
```
### NEW: Item Model `Condition`
- Added support for modern item model `Condition` definitions.
```yaml
MagicShield:
Material: SHIELD
Generation:
Model: item/magic_shield
Condition:
Property: minecraft:using_item
Model: item/magic_shield_blocking
```
### NEW: Item Model `Select`
- Added support for modern item model `Select` definitions.
```yaml
MenuIcon:
Material: PAPER
Generation:
Model: item/menu_icon
Select:
Property: minecraft:display_context
Cases:
- When:
- gui
Model: item/menu_icon_gui
```
### NEW: Item Model `Composite`
- Added support for modern item model `Composite` definitions.
```yaml
LayeredBlade:
Material: DIAMOND_SWORD
Generation:
Composite:
- Model: item/blade_base
- Model: item/blade_gem_overlay
```
### NEW: Item Model `RangeDispatch`
- Added support for modern item model `RangeDispatch` definitions.
```yaml
ChargedBow:
Material: BOW
Generation:
Model: item/charged_bow
RangeDispatch:
Property: minecraft:use_duration
Scale: 0.05
Entries:
- Threshold: 0.65
Model: item/charged_bow_pulling_1
- Threshold: 0.9
Model: item/charged_bow_pulling_2
```
### NEW: Item Model Tints
- Added support for extra tint entries during item model generation.
- Supports constant, custom model data, dye, firework, grass, map color, potion, and team tint types.
```yaml
TintedBlade:
Material: DIAMOND_SWORD
Generation:
Model: item/tinted_blade
Tint:
- Type: DYE
Index: 0
Default: "#FFFFFF"
```
### NEW: Empty Item Model Definitions
- Added `Empty: true` for modern item model branches that should intentionally render nothing.
```yaml
HiddenCaseItem:
Material: PAPER
Generation:
Model: item/base_icon
Select:
Property: minecraft:display_context
Cases:
- Value: gui
Empty: true
```
### NEW: Custom Armor Components
- Added component-based armor generation support.
- Custom armor generation now defaults to the component method in the generated config.
```yaml
CrystalHelmet:
Material: DIAMOND_HELMET
Generation:
Armor:
Texture: armor/crystal
Type: COMPONENT
```
### NEW: Custom Painting Generation
- Added `Type: PAINTING` items for generating 1.21.4+ painting variants.
```yaml
AncientMapPainting:
Type: PAINTING
Material: PAINTING
Painting:
Width: 2
Height: 1
Texture: painting/ancient_map
Title: "Ancient Map"
Author: "Mythic"
```
### Pack Merging
- Added MythicHUD pack merging.
- Improved HappyHUD, Emojy, and ModelEngine pack merging.
- Pack-level `assets/merge` folders are now copied into the generated pack.
- JSON and `pack.mcmeta` files are merged instead of blindly replaced where possible.
### Generated Assets
- Added generated sound asset support.
- Added generated tooltip asset support.
- Added generated font asset support.
- Added custom painting atlas/data generation.
- Added 1.21.11 atlas split handling for newer pack formats.
- Added missing texture patching for missing or `missingno` model references.
- Added path sanitizing for generated model paths so invalid resource-location characters are replaced safely.
Item Changes
------------
### NEW: Custom Equippables
- Added custom equippable slots backed by player variables.
- Custom slots can define a checked vanilla slot and equip conditions.
- Items can use custom slots through `EquipSlot`.
```yaml
Configuration:
Equippables:
Enabled: true
CustomSlots:
- Id: RING
EquipSlot: HAND
Display: Ring
EquipConditions:
- haspermission{p=items.ring} true
RubyRing:
Material: AMETHYST_SHARD
EquipSlot: RING
```
### NEW: `Options.InfiniteQuiver`
- Added `Options.InfiniteQuiver` to allow bows to shoot without consuming arrows.
- Extended `Options.InfiniteQuiver` support to crossbows.
```yaml
EndlessBow:
Material: BOW
Options:
InfiniteQuiver: true
```
### NEW: `Options.PreventBlockInteraction`
- Added `Options.PreventBlockInteraction` to stop an item from right-clicking blocks when used.
```yaml
MagicWand:
Material: BLAZE_ROD
Options:
PreventBlockInteraction: true
```
### NEW: Nexo Items
- Added `NexoId` support for generating Crucible items from Nexo item definitions.
```yaml
NexoBackedItem:
Material: PAPER
NexoId: ruby_sword
Display: "<red>Ruby Sword"
```
### NEW: Multiline Augment Tooltips
- Augment `Tooltip` can now be a list.
```yaml
SharpnessAugment:
Material: AMETHYST_SHARD
Augmentation:
Type: GEM
Tooltip:
- "<gray>Increases weapon damage"
- "<dark_gray>Socket this into a weapon"
```
### NEW: Item Upgrade `u` Formula Variable
- Added `u` to item upgrade stat formulas.
- `u` represents the upgrade level relative to the item's default level.
```yaml
UpgradeSword:
Material: IRON_SWORD
Upgrades:
DefaultLevel: 1
Stats:
Equations:
- DAMAGE ADDITIVE v+u*0.5
```
### Item Updates
- Upgraded item levels now persist across item updates.
- Item stat ratios can be preserved during item updates.
- Item stats are now removed when they no longer exist on the updated item definition.
- Lore updates now work on items that do not use a `LoreTemplate`.
- Lore wrapping now respects explicit newlines.
### ItemData
- `ItemData` placeholders now support text wrapping.
- Added `wrapLinePrefix`, `wrapPrefix`, and `wlp` aliases for `wrapLineColor`.
- Formatting tags such as `<red>` are ignored when calculating wrap length.
- `\n` in item lore is now supported.
```yaml
StoryItem:
Material: PAPER
ItemData:
description: "<gray>This is a long description that should wrap cleanly."
Lore:
- "<item.data.description{wrap=32;wrapLinePrefix=\"<gray>\"}>"
```
Furniture Changes
-----------------
### NEW: Connectable Furniture
- Added `ConnectionModels` for furniture that changes model based on neighboring furniture of the same type.
- Supports default, straight, left end, right end, inner corner, and outer corner models.
```yaml
CastleWall:
Type: FURNITURE
Furniture:
Type: DISPLAY
ConnectionModels:
Default: mythic:item/wall_default
Straight: mythic:item/wall_straight
Left: mythic:item/wall_left
Right: mythic:item/wall_right
Inner: mythic:item/wall_inner
Outer: mythic:item/wall_outer
```
### NEW: Furniture Occlusion Culling
- Added optional per-player furniture culling behind solid blocks.
- Can be configured globally and overridden per furniture with `Cullable`.
```yaml
Configuration:
Furniture:
Culling:
Enabled: true
Interval: 1
ForceAll: true
MinDistance: 0.0
MaxDistance: 64.0
PaddingWidth: 0.0
PaddingHeight: 0.0
HiddenStatue:
Type: FURNITURE
Furniture:
Cullable: true
```
### NEW: WorldEdit Furniture Copy/Paste
- Added WorldEdit support for copying and pasting furniture entities.
- Furniture type, state, color, orientation, and variables are restored during paste.
```text
//copy -e
//paste -e
```
### Furniture Generation
- Furniture now uses generated item models when explicit furniture models are not provided.
- Furniture hitboxes no longer depend on old pre-1.19.4 checks.
- Furniture state lights and barriers are cleaned up more reliably when returning to a default state.
- Furniture middle-click pickup now handles newer pick-item behavior.
Custom Blocks
-------------
### NEW: `~onRandomTick` for Custom Blocks
- Custom block skills can now run from random tick logic.
- The optional interval uses vanilla-style random tick chance math.
```yaml
GlowingOre:
Type: BLOCK
CustomBlockSkills:
- effect:particles{p=glow;a=5} @self ~onRandomTick:4096
```
### Custom Block Handling
- Custom block placement is now prevented on entities and functional blocks when appropriate.
- Note block custom block state protection was improved.
- Custom block random tick skills run from a block caster so location-based skills have a proper origin.
Triggers
--------
### NEW: `~onInventoryPlace`
- Added item trigger for placing an item into an inventory slot.
- Exposes item and container context variables/placeholders.
```yaml
TrackedGem:
Material: EMERALD
Skills:
- message{m="Placed <item.name> into <container.type>"} @self ~onInventoryPlace
```
### NEW: `~onInventoryTake`
- Added item trigger for taking an item from an inventory slot.
- Exposes item and container context variables/placeholders.
```yaml
TrackedGem:
Material: EMERALD
Skills:
- message{m="Took <item.amount>x <item.type>"} @self ~onInventoryTake
```
### NEW: `~onInventoryMove`
- Added item trigger for shift-click and hotbar inventory movement.
- Resolves the target inventory so conditions can check where the item is moving.
```yaml
TrackedGem:
Material: EMERALD
Skills:
- message{m="Moved item into <container.type>"} @self ~onInventoryMove
```
### NEW: `~onDragDrop`
- Added item trigger for dragging one item onto another item.
- Exposes cursor item and target item context.
```yaml
SocketGem:
Material: AMETHYST_SHARD
Skills:
- message{m="Dropped <item.type> onto <skill.var.target.type>"} @self ~onDragDrop
```
### NEW: `~onUsePrimary`
- Added a primary-use item trigger that ignores incidental right-clicks such as eating, blocking, drawing bows, using rods, placing blocks, and interacting with functional blocks.
```yaml
CasterWand:
Material: BLAZE_ROD
Skills:
- skill{s=CastWandSpell} @self ~onUsePrimary
```
### NEW: `~onAugmentation`
- Added augmentation trigger aliases for augment application.
```yaml
SocketableSword:
Material: IRON_SWORD
Skills:
- message{m="Augmented <item.name>"} @self ~onAugmentation
```
### NEW: `~onRandomTick` for Furniture
- Furniture skills can now run from random tick logic.
```yaml
MysticLamp:
Type: FURNITURE
FurnitureSkills:
- effect:particles{p=end_rod;a=2} @self ~onRandomTick:2048
```
### Trigger Fixes
- Fixed `~onHeld` and `~onUnHeld` not firing when pick-block changes the held item.
- Fixed wrong bow power being passed to `~onShoot` on newer versions.
- Fixed held item skills persisting after hand item changes.
Mechanics
---------
### ConsumeItem
- `consumeitem` now supports runtime item filters with placeholders and variables.
- Runtime matchers are cached after the filter resolves.
```yaml
- consumeitem{item="<caster.var.required_item>";amount=1;runtime=true}
```
### Durability Mechanics
- Durability mechanics now support placeholders in the amount field.
- `consumeuseddurability` now calls `PlayerItemDamageEvent` when applying positive damage.
- `consumeuseddurability` now damages the actual used inventory item instead of a stale item reference.
```yaml
- consumeuseddurability{amount="<caster.var.durability_cost>";breakitem=true}
```
### RegenerateLore / UpdateLore
- `regenerateLore` / `updateLore` can now update Crucible items even when the item does not use a lore template.
```yaml
- updateLore
```
Conditions
----------
### NEW: `containerType`
- Added `containerType`, with `inventoryType` and `container` aliases.
- Checks the active container type from inventory interaction metadata.
```yaml
Conditions:
- containerType{type=CHEST,BARREL} true
```
### HasItem
- `hasItem` now supports placeholder and variable-backed item filters.
- Runtime item filter resolution now uses the caster context in skill metadata.
```yaml
Conditions:
- hasItem{i="<caster.var.required_item>"} true
```
Placeholders
------------
### NEW: Item Interaction Placeholders
- Added item context placeholders for inventory and drag/drop triggers.
- New placeholders include `<item.amount>`, `<item.crucibleid>`, `<item.custommodeldata>`, `<item.enchants>`, `<item.equip.slot>`, `<item.name>`, `<item.slot>`, and `<item.unbreakable>`.
```yaml
- message{m="<item.amount>x <item.name> in slot <item.slot>"} @self ~onInventoryTake
```
### NEW: Container Placeholders
- Added target container placeholders for container size, item counts, slot type, and slot amount.
```yaml
- message{m="Chest size: <container.size>, diamonds: <container.count.DIAMOND>"} @self
- message{m="Slot 0: <container.slot.0.amount>x <container.slot.0.type>"} @self
```
### NEW: Open Container Placeholders
- Added open-container variants for reading the player's currently open external inventory.
```yaml
- message{m="Open size: <open.container.size>"} @self
- message{m="Open slot 4: <open.container.slot.4.type>"} @self
```
### NEW: Set Pieces Placeholder
- Added `<caster.set.SET_ID.pieces>` style placeholders for equipment set piece counts.
```yaml
- message{m="Set pieces: <caster.set.NetherKnight.pieces>"} @self
```
### NEW: Caster Furniture Variable Placeholder
- Added `<caster.furniture.var.KEY>` for reading furniture variables from the caster furniture.
```yaml
- message{m="Charge: <caster.furniture.var.charge>"} @self
```
### Placeholder Engine Updates
- Updated Crucible placeholders to use the newer Mythic placeholder API.
- Added wildcard support for `fontimage.*` / `emoji` placeholders.
- Added entity-scoped item NBT placeholders.
- Added slot-specific item NBT placeholder support through `<item.SLOT.nbt>`.
- `item.stat` and `item.stat.display` now work during item generation and outside lore-only contexts.
- Fixed conditional parsing in `ItemData` placeholders.
- Fixed `<item.data>` edge cases.
- Fixed `<item.upgrade.description>` and `<item.upgrade/level.description>` when no live item stack is provided.
Custom Menus
------------
### NEW: `armor` Button Function
- Added a custom menu button function that exposes a vanilla armor or hand slot in a menu.
```yaml
HelmetButton:
Mapping: H
Function:
Type: armor
Slot: HEAD
```
### NEW: `custom_equippable` Button Function
- Added a custom menu button function for custom equippable slots.
```yaml
RingButton:
Mapping: R
Function:
Type: custom_equippable
Slot: RING
```
Recipes
-------
### NEW: Recipe Groups
- Added `RecipeGroup` so recipes can be assigned to a Bukkit recipe-book group.
```yaml
MySword:
Material: IRON_SWORD
Recipes:
shaped_sword:
Type: SHAPED
RecipeGroup: mythic_weapons
Ingredients:
- "m IRON_INGOT 1|m IRON_INGOT 1|m IRON_INGOT 1"
```
### NEW: `IngredientsLeftover` Durability Suffixes
- `IngredientsLeftover` now supports `:number` and `:-number` suffixes.
- Positive numbers set remaining durability.
- Negative numbers subtract durability from the leftover item.
```yaml
RepairRecipe:
Material: IRON_SWORD
Recipes:
repair:
Type: SHAPED
IngredientsLeftover:
- "m IRON_PICKAXE 1:-5|v AIR 0|v AIR 0"
```
### Crafting Performance
- Improved recipe matching performance.
- Fixed unbounded list growth in crafting stations.
- Improved ItemUpdateManager detection speed.
- Added runtime item filter support for Crucible `hasitem` and `consumeitem`.
External Compatibilities
------------------------
### Nexo
- Added Nexo item support through `NexoId`.
- Crucible reloads when Nexo item data finishes loading.
- Added Nexo MiniMessage parsing support.
```yaml
NexoDisplayItem:
Material: PAPER
NexoId: custom_hat
Display: "<gold>Custom Hat"
```
### WorldEdit
- Added furniture copy/paste support when using entity-aware WorldEdit operations.
- Existing custom block parser support now uses the generated pack namespace.
```text
//copy -e
//paste -e
```
### Folia
- Added Folia compatibility metadata and scheduler adjustments.
- Fixed Folia issues with furniture occlusion culling.
- Fixed async block modification caused by furniture conditions.
### Paper
- Added Paper `26.1.x` volatile support.
- Added Paper 1.21.5+ configuration-phase pack dispatch support.
### Pack Integrations
- Improved ModelEngine pack merging.
- Added MythicHUD pack merging.
- Improved HappyHUD and Emojy pack merging.
- Added support for MCPacks deployment.
API
---
- Moved public `CustomBlockData` into the API module.
- Added `BowBridge` API for version-specific bow and crossbow handling.
- Added custom equippable slot API support.
- Exposed custom equipment API helpers.
- Improved `CrucibleSupport#addItemToGeneration` so externally generated items are registered with the pack generator.
- Added generation feedback for generated item model keys.
- Added generated sound and generated tooltip lookup helpers.
Bug Fixes & Optimizations
-------------------------
- Optimized pack generation performance.
- Optimized Blockbench model parsing during generation.
- Optimized ItemUpdateManager detection speed.
- Optimized crafting recipe matching and crafting station memory growth.
- Fixed startup load order issues after the Gradle/NMS refactor.
- Fixed duplicate vanilla path pack generation.
- Fixed false missing-texture warnings from pack template inheritance.
- Fixed false missing-texture warnings for bows and crossbows.
- Fixed generated overlay names so they respect lowercase resource-location casing rules.
- Fixed model paths with invalid characters by sanitizing them before generation.
- Fixed generated pack configuration phase blocking until the client resolves the pack.
- Fixed S3 deployment options for path-style URLs, chunked encoding, public-read ACLs, and regions.
- Fixed item stats not applying for newly defined stats.
- Fixed item stats not being removed when the new item definition removes them.
- Fixed stat randomization for crafting.
- Fixed premature stat rounding on new lore generation.
- Fixed stat ratio persistence on item updates.
- Fixed upgraded item levels being lost during item updates.
- Fixed `ItemUpdater` NPEs when an old stat range is no longer present.
- Fixed item updates relocking unlocked augment slots.
- Fixed lore templates not splitting wrapped lines on newline.
- Fixed `updateLore` for items without a lore template.
- Fixed `ItemData` placeholders when no live item stack is available.
- Fixed conditional placeholder parsing in `ItemData` placeholders.
- Fixed `ItemData` wrap length counting MiniMessage formatting tags as visible characters.
- Fixed `<item.upgrade/level.description>` edge cases.
- Fixed `consumeitem` failures with dynamic filters.
- Fixed `consumeUsedDurability` so slot swapping cannot avoid durability loss.
- Fixed custom durability mechanics to fire `PlayerItemDamageEvent`.
- Fixed several equip slot null and edge-case errors.
- Fixed ArmorEquipEvent null log spam.
- Fixed lore updates after item updates.
- Fixed custom equippable slot edge cases.
- Fixed custom equipment API edge cases.
- Fixed Nexo component conversion issues.
- Fixed additional Nexo compatibility issues.
- Fixed fishing rod display state while cast.
- Fixed wrong bow power being passed to `~onShoot` on newer versions.
- Fixed furniture variables in multiple reload and persistence cases.
- Fixed furniture middle-click pickup.
- Fixed furniture state lights and barriers not being removed when returning to the default state.
- Fixed `GlowingFrame` not working for furniture states.
- Fixed furniture not auto-mapping generated models when none is defined.
- Fixed async block modification caused by furniture conditions.
- Fixed custom block placement on entities and functional blocks.
- Fixed note block custom block state protection.
- Fixed recipe leftover durability behavior.
- Fixed recipe matching performance regressions.
- Fixed bag auto-pickup issues and PlaceholderAPI initialization issues.
- Fixed self-referential item conditions causing stack overflow on reload.
- Fixed `hasItem` runtime placeholders resolving without the caster context.
- Fixed merge logic not respecting configured toggles.
- Fixed generated custom armor rotation limits for newer versions.
- Fixed several Paper `26.1.x` follow-up issues.
Older Changelogs
================
- [2.X.X Changelogs](/2.x.x_changelogs)
- [1.6.X Changelogs](/1.6.x_changelogs)
- [1.5.X Changelogs](/1.5.x_changelogs)
- [1.4.X Changelogs](/1.4.x_changelogs)
- [1.3.X Changelogs](/1.3.x_changelogs)
- [1.2.X Changelogs](/1.2.x_changelogs)
- [1.1.X Changelogs](/1.1.x_changelogs)
- [1.0.X Changelogs](/1.0.x_changelogs)
- [Pre-1.0.0 Changelogs](/pre-1.0_changelogs)} - [Pre-1.0.0 Changelogs](/pre-1.0_changelogs)}
\ No newline at end of file