[Fabric] 1.20.1 | V2001.2.0.0 RELEASE
Curse Maven Snippet
What's new
v2001.2.0.0 Release | Sep 30, 2026 (Minecraft 1.20.1 backport)
✨ New Features
- CoolCatLib is split in two mods: CoolCatLib: Core (
coolcatcore, packagenet.ixdarklord.coolcatcore), this one, and CoolCatLib: Canvas (coolcatcanvas), which now holds screen effects, skyboxes, GUI widgets,RenderUtilsandEasing. The mod id, package, asset namespace, Fabric entrypoints (coolcatcore:common, ...) and commands (/coolcatcore,/coolcatcore_client) all changed fromcoolcatlib. - A cross-loader platform layer, so mods built on CoolCatLib: Core no longer need Architectury API:
- Events (
api.event.v2):EventInvokerkeeps listeners in common code, ordered byEventPhase, and is found by its listener type (EventInvoker.lookup(ServerTickEvents.End.class)) or its constant (ServerTickEvents.END).EventInvoker.create(Type.class)makes a mod's own event, combining listeners by return type (void,EventResult,EventResultHolder,boolean). - Built-in events: server lifecycle and ticks, datapack contents sync (
ServerLifecycleEvents.SYNC_DATA_PACK_CONTENTS: per player on login and after/reload), player join/leave/tick, entity load, block break/place, commands; client ticks, player join/leave, HUD rendering, item tooltips, client commands. api.registry:DeferredRegister/RegistryEntry,CreativeTabs,ReloadListeners.api.menu.ExtendedMenus: menu types that open with extra data.api.network.Network: serverbound/clientbound payloads and sending.Network.canPlayerReceive(player, type)tells whether a player's connection accepts a payload (false for clients without the mod and for GameTest mock players).- Record payloads without a
StreamCodec:Network.registerServerbound(MyPayload.class, receiver)(or with an explicitType) derives the codec from the record's components throughPayloadCodecs, which knows primitives, strings, common Minecraft types, enums, nested records, arrays,Optional,List,Set,Map,EitherandResourceKey. Other types are added withPayloadCodecs.register/registerFactory; registering a payload with a component type that has no codec throws right away, naming the component.
- Record payloads without a
api.client.registry: key mappings, menu screens, tooltip components.api.platform.Platform: loader, environment, mod checks, folders, the running server, fake players.- Mod constructors (
api.core):ModConstructor(both sides),ClientModConstructor,ServerModConstructor(dedicated server) andDataGenerationConstructorare written once in common code, each with a construct stage and a setup stage (DataGenerationContext.addProviderfor data providers).- Fabric needs no Java entry class: list them under the
coolcatcore:common,coolcatcore:client,coolcatcore:serverandcoolcatcore:datagenentrypoints, plusapi.core.fabric.FabricDataGenerationEntrypointunderfabric-datagen. - Forge: extend
api.core.forge.ForgeModEntrypointin the@Modclass (its constructor takes theFMLJavaModLoadingContextForge passes to@Modconstructors) and callcommon(...),client(() -> ...),server(() -> ...),dataGeneration(...); the mod id comes from the context.
- Fabric needs no Java entry class: list them under the
- Events (
EventResult.pass()/interrupt()/allow()/deny(), andEventResultHolder.result()/getValue().- A config system (
api.config):- Declare configs with
Config.builder(modId, scope)(typed values, nested groups, presets) or from an annotated class withConfigObject.register. - Scopes:
CLIENT,COMMON,SERVER(synced to players) andWORLD(stored per world, seeded fromdefaultconfigs, synced). - Types: booleans, ranged numbers (optionally sliders), strings (length/pattern), enums, colors, ids, lists, and any
Codec; customConfigTypes with their own editors. - TOML (default) and JSON5 files with generated comments; a config whose format changes converts its old file once (kept as
.bak); broken files are backed up;version/migrationandaliaseshandle renamed or moved settings. - Hot reloading of edited files, change listeners and
ConfigEvents:LOADED(first read),RELOADED(hot reload, the reload command orConfig.reload()),UNLOADING(a world config before its server's values are dropped),VALUE_CHANGED(each value, with its old and new value),CHANGED(once per batch),SAVEDandSYNCED. serverOnly()values that never leave the server; operators edit synced configs in-game with permission checks.- Generated config screen: search, undo/redo, reset, presets, validation, dependencies (
enabledWhen), restart notices and list editing. Linked from the Forge mod list and Mod Menu. /coolcatcore config(server) and/coolcatcore_client config(client) commands: list, get, set, reset, reload, preset, open.STARTUPconfigs, read before content is registered (for item properties, which items exist...). Their values stay fixed until a restart; edits are saved for the next start. Joining a server compares them before entering the world: values must match by default (the client is offered to adopt the server's),useServerValue()values are taken from the server while connected, andlocalOnly()values stay per side.- Category popups: one category of a config in a small window with Save and Cancel, floating over the current screen or the game, e.g.
ConfigScreens.openCategory("mymod", "client/rendering"),ConfigScreens.categoryPopup(parent, config, path), or/coolcatcore_client config open <mod> <category>(with path suggestions). A single setting's path shows just that setting. - A color picker for color values (a popup with saturation/brightness, hue and alpha, hex input and dye colors), also available as
ConfigScreens.colorPicker. - The main config screen (shown for every mod, even one with a single config): a header with the mod's icon (a "?" when it has none; the list of every mod's configs has its own icon), and each config as a portrait navigation card with its own artwork (faint, brightening on hover; CoolCatLib: Core's per scope, or the mod's own at
assets/<modid>/textures/gui/config/cards/<config name>.png), its scope icon and a short label like "Server" (config.<modid>.<name>.label). Cards are centered, grow when hovered, and show a tooltip with the config's scope, contents, file and access. Mod Menu's CoolCatLib: Core button opens CoolCatLib: Core's own settings. - Page transitions: a config page's panels glide a little way into place (up from below when opened, down from above when going back, a shorter rise when opened from elsewhere) while growing from slightly smaller; the background stays still.
- Config screen effects: animations a theme names by id, drawn behind the panels, over the whole screen, and over each widget (buttons, toggles, sliders, text fields, cards, popup panels). Mods register their own on the client with
ConfigEffects.register(id, ConfigEffect)and use them withConfigTheme.Builder.effects(...),ConfigBuilder.effects(...)for one config, or"effects"inconfig_theme.json; an unknown id is skipped and an effect that throws is switched off, each logged once. The built-inConfigTheme.STARFALL, every theme's default, draws soft glows in the accent and small faint stars falling from the top, shifting with the mouse by depth (parallax). CoolCatLib: Core's client config turns effects and the page transitions on or off (Effects > Theme Effects / Page Transitions); both are always off on the Fast graphics preset. - Redesigned config screens: a top bar (title, scope badges, search), a category sidebar, settings with descriptions and nested sections, and a bottom bar with the unsaved-changes status and actions; toggle switches, sliders, selectors and flat buttons; presets, confirmations and the color picker as popups. Icons are 64x64 textures in
assets/coolcatcore/textures/gui/config/icons/(smoothly filtered), replaceable by resource packs. ConfigTheme: each mod's own look, set per mod (ConfigTheme.setForMod) or per config (ConfigBuilder.theme/background): a fullConfigColorScheme(presetsDARK,LIGHT, andtinted(accent)for the dark scheme shaded toward the mod's color), a background texture by its path (cover, stretch or tile), the texture's opacity (textureOpacity, letting the panorama or world show through) and the backdrop color's opacity over the background (backgroundOpacity). Players can scale both for every mod in CoolCatLib: Core's client config (Background > Backdrop Opacity / Texture Opacity). By default the screens are see-through to the title panorama or the world. Resource packs can restyle a mod withassets/<modid>/coolcatcore/config_theme.json.- Popup panel sprites:
ConfigTheme.Builder.popupSprite(orpopup_spriteinconfig_theme.json) draws a nine-slice GUI sprite as the panel of popups (category popups, confirmations, the color picker) instead of the flat panel, andConfigScreens.categoryPopup(parent, config, path, theme)opens a category popup with its own theme, e.g. to match the screen it's opened from.- Toggle switches have an outline on their track: the panel border while off, a darker shade of the accent as they turn on.
- Popups keep their buttons in a footer strip along the bottom and their content above it, so a sprite's footer band sits behind the buttons only (the color picker's Cancel and Done moved there).
- The config list shows each mod's icon (a theme can set another); config pages and their cards show an icon of their kind (client, common, server, world, startup).
Platform.getModName.- Dark and light mode: a sun/moon switch in every config screen's top bar, remembered in CoolCatLib: Core's own client config (
themeMode). Each theme has a light scheme too (ConfigTheme.Builder.lightColors, by default derived from the mod's accent;light_base/light_colorsinconfig_theme.json). - The main config screen's search bar searches every config it lists (names, keys, comments, group names, values), with results grouped by config; opening a result shows that config filtered to it. A config's own search covers only that config.
- Declare configs with
- Attachments, containers and handlers for items, blocks and entities:
api.attachment: typed data any entity (players included), block entity or item stack can carry. Each mod creates its ownAttachmentRegistry.create(modId)(and callsregister()while it initialises); its values are stored under its own id, in the<modid>:attachmentsitem component and a<modid>:attachmentstag in entity and block entity data. Declared once (ATTACHMENTS.builder(name, codec, default)), then used asMADNESS.get(player),set,update,modify,reset, or throughAttachmentHolder.of(...).- Persistent attachments save with their holder;
transientBuilderones never do.copyOnDeath()keeps a player's value through death (always kept through dimension changes and the End exit);keepOnDrop()carries a block entity's value into its dropped item and back when placed. sync(SyncPolicy):SELF(the player it belongs to),TRACKING,ALL, or any predicate. Only changed values are sent, at most once per tick; everything when a player starts seeing the holder, receives its chunk, joins, respawns or changes dimension.- On item stacks, defaults aren't stored, so stacks still stack.
- Persistent attachments save with their holder;
AttachmentEvents:CHANGING(cancel a change or replace the value),ADDED,CHANGED(in-place changes included),REMOVED,START_TRACKING/STOP_TRACKING(a player starts or stops receiving a holder's data) andRECEIVED(synced values arrived on the client), plus typed per-attachment helpers (onChanged(MADNESS, ...)).api.container:ContainerLayout(slot filters, limits, rolesSTORAGE/INPUT/OUTPUT/INTERNAL, which slots each face reaches) makesSlotContainers, vanillaContainers with insert/extract, listeners and layout-aware menu slots.AttachmentRegistry.containerstores one on any entity or block entity (saved and synced with the rest);ItemContainerskeeps one in a stack (ContainerItemfor items that have one);ItemTransfermoves items between any containers through faces.api.block:ExtendedBlockEntity(attachment shortcuts, handlers,serverTick/clientTickwithExtendedBlockEntity.ticker) andExtendedContainerBlockEntity(an inventory hoppers and comparators use; contents spill or, withkeepContentsOnBreak, stay in the item).api.handler:HandlerTypefor anything holders hand out (inventories, energy...), from the holder itself (HandlerProvider,HandlerMap) or registered providers and fallbacks for blocks, block entities, entities and items.HandlerTypes.CONTAINERalso finds vanilla containers (double chests as one).BlockHandlerCachekeeps a lookup until the block changes, its block entity goes, orHandlerType.invalidateis called.- Other mods reach these containers through each loader's own system, following the layout's filters, roles and limits: Forge item handler capabilities (
ForgeCapabilities.ITEM_HANDLERon block entities, entities andContainerItemstacks) and Fabric's Transfer API (ItemStorage.SIDEDfor blocks). api.registry.BlockEntityTypes.create: block entity types from common code.- Storage menus (
api.menu.StorageMenuDefinition): a menu for a block's or an item's inventory, declared once (StorageMenuDefinition.grid(columns, rows)or placed slot by slot), registered withcreateMenuTypeand opened withopen(player, blockEntity, title)oropen(player, hand, title). Slots follow the container's layout and shift-click; the menu closes when the block is removed, the player walks away, or the item leaves its slot (which stays locked meanwhile).sync(attachment)andsyncValue(...)send extra values to the screen while it's open, andbutton(id, action)runs screen buttons on the server.api.client.gui.screens.StorageScreendraws any of these menus with no texture, and can be extended.
⚙️ Refactoring
- Rewrote the v2 event system (the lookup-based skeleton had no events);
EventInvokerRegistrywas removed.
🔁 Differences from the 26.1.2 version (Minecraft 1.20.1)
- Built for Forge 47 and Fabric (Fabric API 0.92.6) on Java 17, with the same features as CoolCatLib: Core for 26.1.2, except where 1.20.1 has no equivalent:
- Networking: 1.20.1 has no payload types, so Core brings its own
api.network.CustomPacketPayloadand theapi.network.codecpackage (StreamCodec,ByteBufCodecs, ...;ByteBufCodecsalso holds the codecs newer Minecraft keeps on vanilla classes, such asRESOURCE_LOCATION,BLOCK_POS,ITEM_STACK,COMPONENT). On Forge every payload travels on onecoolcatcore:networkchannel; on Fabric each payload type is its own channel. - There is no configuration phase: configuration payloads (config sync and the
STARTUPconfig check) are sent in the login phase instead. api.utils.ARGB: the packed colour helpers newer Minecraft has asnet.minecraft.util.ARGB.- GUI: everything draws with
GuiGraphics; methods namedextract...on 26.1.2 arerender...again (StyledScreen.renderBackground/renderPanels/renderTitle,StyledPopup.renderPopup,FlatButton.renderContents,StorageScreen.renderPanel,ConfigEffect.renderBackground/renderForeground/renderWidget), and input uses 1.20.1'smouseClicked(double, double, int),keyPressed(int, int, int), ... signatures. GUI sprites (config theme popup sprites included) are textures undertextures/gui/sprites/, with their stretch, tile or nine-slice scaling read from the.mcmeta; a theme'spopupSpritemay also be a.pngtexture path. The menu blur is always on, at the default strength. Config screen effects and page transitions are off on the "Fast" graphics setting (1.20.1's equivalent of the Fast graphics preset). - Events:
ClientGuiEventsHUD listeners take(GuiGraphics, float partialTick);ItemTooltipEventshas no tooltip context. - Attachments: item stack values live in the stack's NBT (
"<modid>:attachments"), not in a data component (AttachmentRegistry.componentType()/bundleComponent()don't exist).keepOnDropvalues reach the dropped block item through the loot table:AttachmentRegistry.copyKeptOnDrop()gives thecopy_nbtfunction. - Containers:
SlotContainer.toContents/fromContentsuse aCompoundTag(a vanillaItemslist);ItemContainerskeeps contents inBlockEntityTag.Itemsfor block items andItemsfor other items. Blocks of anExtendedContainerBlockEntitycallExtendedContainerBlockEntity.onBlockRemoved(state, level, pos, newState)fromonRemoveso the contents spill, and akeepContentsOnBreaklayout needs acopy_nbtofItemsintoBlockEntityTag.Itemsin the loot table. There's no Fabric item storage lookup forContainerItemstacks. - Config:
ConfigBuilder.editPermission(int level)/Config.editPermission()use a permission level (default 2) instead of aPermission. ItemDataComponent(ResourceLocation, Codec)andDataComponentare backed by the stack's NBT.- Brewing:
BrewingBuildertakesPotions;RegisterBrewingRecipesEvent.invokeEvent()takes no builder and fires once per game. On Fabric, custom recipes are read throughapi.brewing.fabric.FabricBrewingRecipes(thePotionBrewingExt/PotionBrewingBuilderExtinterfaces don't exist on 1.20.1). FabricLanguageWrappertakes aFabricDataOutput.Platform.isForge()andPlatform.Loader.FORGEinstead ofisNeoForge()/NEOFORGE.
- Networking: 1.20.1 has no payload types, so Core brings its own
- Carries the brewing fix of v2001.1.0.1:
RegisterBrewingRecipesEventfires during Forge's common setup.
This mod has no additional files

