Tags
Creators
Details
Licensed ARR
Published 3 years ago
Updated last month
All versions
1.0.9
Release
thematic-heroes-1.20.1-1.0.9.jarlast month 3,000
Uploaded by
Compatibility
Minecraft: Java Edition
1.20–1.20.1
Platform
Fabric
Supported environments
Client and server
Required content
Any compatible version
Any compatible version
Any compatible version
Any compatible version
Any compatible version
Any compatible version
Changes
Thematic Heroes v1.0.9
- Update pack version
- Fix version
- Update changelog
- fixes
-
- Spectre & Captain Atom Remodels
- chore: more fixes
- chore: fixes
- feat: tilt the whole mannequin, and move the cape off its shoulders Facing turned the figure but nothing tipped it, so a mannequin could not be laid out flat or leaned into a wind. Tilt does that, and both it and Facing now turn about the block's base centre rather than inside each rig - which is where the feet are, now that the suit stands on the block, so a tilt tips the figure over instead of swinging it about a point near its head. Applying them once above both rigs also means the stub and the suit cannot drift apart under them. The cape already follows the back: it hangs off armorBody, so the torso bone carries it, and it will now carry the whole-body tilt too. What it did not have was any way to be adjusted - so Angle overrides the hang on top of whatever the body is doing, and Up and Back move it off the shoulders in the bone's own space, where Y is up and Z is back. That needed room the panel did not have. The tabs go from three to four - Rotate, Move, Cape, Body - over five shared slider rows, each tab showing as many as it needs. Facing and Scale move onto Body alongside Tilt, which frees the two rows the cape's offsets took. No taller screen. Picking follows the tilt, applying it in the same order the renderer does, so a tipped figure is still clickable where it is drawn. Claude-Session: https://claude.ai/code/session_019MmVQ3xatM6eW5Adx5wLhE
- fix: mirror the stub's limbs, which sat on the wrong sides of a suit GeckoLib negates X when it bakes a model - BakedModelFactory flips bone pivots and cube pivots alike - so a bone authored at x=-4 is drawn at x=+4. The stub is a plain ModelPart rig with no such flip, and I had matched its limbs to the geo's authored coordinates rather than its baked ones. Every limb therefore stood on the opposite side from the sleeve it stands in for, which showed the moment a suit came on or off. Right arm and right leg both move to +X, left to -X, which is where the suit actually draws them once the flip is accounted for: bipedRightArm is authored at -4 and baked to +4, and bipedLeftLeg - which RIGHT_LEG maps to, because the geos cross the legs - is authored at -2 and baked to +2. The picking in the posing screen reads the same pivots, so click targets follow without further change.
- fix: restore the suit's render type after the cape, and hang the glider correctly The cape layer put the matrix back but not the buffer, and that is what painted the whole mannequin in the cape's texture. VertexConsumerProvider.Immediate hands every uncommon render layer the same fallback BufferBuilder, so asking it for the cape's layer rebound that builder to the cape's texture. The layer runs part way through the model, so every bone drawn after it kept writing into that builder. The worn layers have restored it for exactly this reason all along - FastBaseThematicRenderLayer.executeWithErrorHandling re-requests the render type in its finally - and the mannequin layer now does the same. The glider was low and on the chest because it was sharing the cape's transform chain, and it does not have one. The worn path takes the half turn about X but deliberately not the one about Y - that is what puts wings on the back - skips the cape's shoulder translate entirely in favour of a small offset of its own, anchors the whole wing on part 0 rather than bending along its length, and hangs from a fixed angle instead of the authored height, which for a glider is a wing span and would tip it nearly upright. The display path now mirrors all of it, and renders the real armor_glider geo model: it only ever needed the stack from the renderer, for a texture and an animatable, so an overload takes that directly. A suit declaring a glider no longer also reveals its modelled glider bone, which would have hung two off the same back.
- feat: real capes on mannequins, correct placement, two default poses
A mannequin never drew a cape. The State picker only revealed the modelled
broodandgliderbones, and just 23 of 993 armour geos have a brood bone and 16 have a glider one, so for nearly every suit there was nothing there to reveal. What players mean by a cape is a different system: a procedural Cape declared in 243 armour JSONs, drawn by a layer that exists only on the worn renderer. That layer cannot be reused - its base class hard-casts to ThematicArmorRenderer, and Cape.render wants a GeoArmorRenderer and a LivingEntity, neither of which a block entity has. But the physics is not in Cape at all. It lives in a per-entity component ticked only for players and armour stands, and everything derived from it funnels through four numbers per part. So Cape gains a display path that takes those four numbers from a curve instead, and a new layer on the item renderer anchors it to the same armorBody bone the worn one uses. The worn path is untouched; the new layer falls out on its first line for every render that is not a mannequin, which keeps capes off inventory icons. The curve is wind rather than cloth: direction and strength on the Cape tab, so a row of mannequins can be made to stream the same way, plus a slow drift so a still one is not a plank. The simulated numbers are deviations from a straight hang, so dead air is already correct and zero. Placement is settled by measurement rather than guesswork. The pipeline was traced end to end - the fixed display transform, item rendering's -0.5, GeckoLib's +0.51 - and nothing in this mod alters any of it. At 2.675/1.054 the figure stood 2.14 blocks tall with its soles a tenth of a block underground; 2.5/1.08375 makes it exactly two blocks, standing on the block, vanilla-player sized. The stub derives from the same pair. That also turned up the bug behind "the positions don't line up": the posing screen projected limbs with a plain 1/16, while the renderer uses the slightly larger pixel the item pipeline produces. Click targets sat seven percent short of the figure they belonged to. Both now read the same constants. Defaults drop from sixteen poses to Straight and Running. Everything past a neutral stance and a run is a judgement call about a character rather than a starting point, and the library is the place for those. - feat: pose library, undo/redo, and cape states on mannequins Presets become the player's own. The sixteen built-ins now seed a library in config/thematic-poses.nbt the first time it is written, and from then on they are ordinary entries: rename them, overwrite them, delete them. Saving and loading happens in an overlay drawn over the posing screen rather than a screen of its own, since swapping screens would tear down the mannequin's container along with it. Ctrl+Z and Ctrl+Shift+Z (or Ctrl+Y) walk the pose back and forward, Ctrl+C and Ctrl+V move it between mannequins, and Ctrl+Shift+V pastes it mirrored. Undo steps are cut at press-to-release boundaries, so dragging a limb across the screen is one step to undo rather than four hundred. Typing in the name field swallows keys outright: the inherited handler closes the whole screen when it sees the inventory key, which is otherwise just E. Suits carry pieces that only make sense in a particular state -- a brooding cape, a deployed glider, shoulder extensions -- and the item renderer hides every one of them on sight, because an item render has no state to justify them. A mannequin does, so a State picker brings one out and the Cape tab angles it. This is the modelled cape, not the simulated one: that hangs off a LivingEntity through a layer on the worn renderer, and a block entity has none to give it. Also links the stub's transform to the suit's rather than deriving it separately. Where the suit lands depends on the item pipeline applying the fixed display transform and two translations of its own after ours, so the hand-tuned originals are restored as the source of truth and the stub is placed by the same arithmetic. One pair of constants now moves both.
- feat: lighter posing panel, white titles, eight more pose presets The panel was near-black with the inherited dark-grey titles drawn on top of it, which left "Mannequin" and "Inventory" all but invisible. The background is drawn with fills rather than a texture, so this is a palette change: mid grey for the panel, a lighter bevel, and slots darker than the panel so they read as recessed the way vanilla's do. Both titles are now white with a shadow, via a drawForeground override - the inherited one hardcodes the dark grey that suits vanilla's pale background. Presets go from eight to sixteen: Heroic, Pointing, Waving, Blasting, Blocking, Hero Landing, Crouching and Charging. All follow the rig's conventions - positive pitch forward, positive roll across the body - and the ones that fold at the hip drop the whole figure to match, since the rig has no knees to bend.
- chore: encounters on NPCs
- feat: pose mannequin limbs from a GUI Right-clicking a mannequin now opens a posing screen instead of a bare armour slot. Click a limb in the live preview and drag to swing it, or use the sliders when you want an exact angle; there are presets, mirror, copy/paste between mannequins, and per-limb offsets plus a whole-model scale. The pose is stored on the block entity, rides its existing NBT sync outwards, and comes back as one whole-document packet on mouse release, so dragging a limb costs no network traffic at all. Breaking and replacing a mannequin keeps its pose, via copy_nbt on the loot table. The preview is drawn by the same MannequinRenderer.renderPosed call the world uses, so it is genuinely what will be standing there afterwards. Two conventions in the existing models had to be untangled first. The suit geos disagree with themselves about which side is right -- bipedRightArm sits at x=-4 but bipedRightLeg at x=+2, and 665 of the 690 armour geos defining all four bones agree on that -- so MannequinPart deliberately maps RIGHT_LEG onto bipedLeftLeg to put everything the screen calls "right" on one side of the body. And MannequinModel's pivots were placeholders, with the legs turning about the head; they are re-authored as 32 - geoY to match the suit bone for bone. The suit itself was rendering 7% oversized with its feet a tenth of a block underground, which went unnoticed while it was a rigid figure with the stub hidden inside it, and is corrected here so a posed limb and its sleeve swing together. Performance, since a base can hold a hundred of these. A suit is a few hundred cubes -- the median armour geo is 269 -- so past sixteen blocks the six-cube stub stands in for it. The line-of-sight raycast that culls occluded mannequins is cached against the player's block position rather than run every frame, and ThematicArmorItemRenderer's bone snapshotting now reuses flat buffers instead of allocating a map and an object per bone per frame. For a hall of a hundred suits that is roughly 8,500 cubes a frame instead of 26,900, and some 21,000 fewer allocations.
- revert: drop suit skin mode, keep the vanilla cape hiding Skin mode repainted a suit's exposed skin in the wearer's own complexion, and needed a fair amount of machinery to do it: a composite texture cache, a copy mask, a skin pixel cache and tone sampler, two PlayerSkinTexture mixins, a raw-tag scan in ArmorRegistry so a client connected to a remote server could still read the opt-out tags, and a no_skin tag on seven armors. All of it comes out here. The cape half of the same commit stays. Suppressing a Migrator cape that hangs through a suit's own cape has nothing to do with repainting skin, so CapeFeatureRendererMixin, the hideVanillaCape config and its ModMenu toggle are untouched. Nothing is lost: the original work is still on origin/feat/suit-skin-mode.
- feat: suit skin mode + hide vanilla capes under suits Two client-side appearance options, both off the same Visuals config page. Vanilla cape: nothing suppressed Minecraft's own CapeFeatureRenderer, so a Migrator cape hung straight through a suit's own simulated cape. A HEAD-cancel mixin hides it whenever any ThematicArmor chest piece is worn. On by default. Skin mode: makes a suit show the wearer rather than the character. Two layers, because the armor models are not consistent enough for either alone. Copy. Where a model provably samples the vanilla player-skin layout at one texel per block unit, the wearer's real skin is copied straight in, so their face, stubble and markings come across. This has to be judged per texel, not per rectangle: only 87 of 992 models have a head no other cube overlaps, but 785 keep a usable face once contested texels are subtracted. Recolour. Everything the copy cannot reach -- limbs on models that ignore the vanilla layout, contested parts of a face, bare torso -- is found by colour and repainted in the wearer's complexion, each texel keeping its brightness relative to the suit's median flesh tone so shading survives. An earlier attempt copied by coordinate alone and looked badly wrong, because 602 of 992 models have no vanilla-sized head cube, black_manta's head is 10x6x9, 44 models park 2x2x2 detail cubes at the head's UV origin, and 57 use arm slices like 3.5x6x4. The strict per-texel conformance test is what keeps the copy layer honest; the recolour layer never moves a texel and so cannot misalign at all. Masked suits need no special handling: Batman and Spider-Man contain no flesh and match neither layer. Suits whose material merely happens to be flesh-toned are the one case colour cannot judge, and opt out with a no_skin tag -- seeded here for the seven verified by inspection. Opt-out tags are read through a new raw index in ArmorRegistry as well as the item's tag list, because ArmorRegistry.reload only runs from a SERVER_DATA listener and so leaves getTags() empty on clients connected to a remote server. Also widens SliderWidget.setValue to extendable. Cloth Config declares its own setValue, which only collides with the final vanilla method once Loom remaps Minecraft into yarn names, crashing every config screen -- including Cloth's own demo -- in dev. Unrelated to skin mode but needed to reach the toggle. Claude-Session: https://claude.ai/code/session_01PKwNGgVPgtVdXATB5U1AkM
- feat: Movie Poster Blocks
- feat: New Billboards & other deco
- chore: Added parent models for various groups of blocks
- fix: containment suit cooldown never applied on servers The vent's cooldown was charged from inside the last staged ServerTimer callback, 20 ticks after the burst. Those tasks live only in memory and their callbacks are wrapped in a catch that logs at debug level, so logging out mid-vent, a server stop, or any exception in scatterExplosions skipped the one line that charged it -- silently. The suit was then free to vent again as soon as health dropped back under the trigger. Charge it at the burst instead, before any ring goes out, and mirror the expiry as an absolute world-tick deadline in PERSISTENT_DATA. Dying drops the chest piece, and that equipment change wipes the whole ABILITY_DATA map, cooldowns included -- which is exactly what happens after venting at 150 health -- so the cooldown has to survive somewhere the reset cannot reach. onTick puts back whatever is left of it.
- chore: cleaning up timer code, stalk code
- feat: added penguin and twoface brute variants
- chore: cleaned up missions
- fix: incinerating ice CD
- fix: lightning shard fixes
- fix: optimized renderlayer on containment suit, added CD
- feat: missions
- fix: ER on speedsters/flyers
- containment suit
- feat: detective work fixes
- feat: HUD rendering
- feat: new detective work
- feat: Enhanced reflexes rework
- New xray HUD, cosmetic wheel changes, and fast out-of-combat healing
- Ping stuff
- Embrace fear fixes
- Drop the Draco dependency from the shipped jar com.openize:drako was jar-in-jar'd into the mod (375 KB, 247 classes) to decode a single 8.6 KB asset -- assets/thematic/gltf/atom.glb, the only glTF model that ships. Uncompressed, that asset is 22 KB, so Draco was buying ~13 KB of asset at a cost of 375 KB of library. It was also already a dead end for the models that matter: drako 26.3.0 loses every component after the first on multi-component integer GENERIC attributes, so GltfDracoDecoder refused JOINTS_0 outright -- meaning skinned meshes, which is all of the armor models, could never be Draco-compressed anyway. atom.glb is replaced by a decode-and-repack of the exact bytes the game was already producing at runtime, verified value-for-value against the Draco decode (geometry and animation both), so nothing about the render changes. GltfModelLoader now rejects any model declaring extensionsRequired, naming the extension. Nothing read that field before -- the only extension ever supported was Draco -- so without it a Draco-compressed model would fail on a bufferView-less accessor several frames later. Also restores src/test/resources/gltf/atom.gltf, which GlbContainerTest.glbAndEmbeddedBase64DecodeToIdenticalAccessorData has always read but which was never committed, so that test failed on every run. CI never caught it: stage and finalize both build with -x test. Claude-Session: https://claude.ai/code/session_01RF5QvS67ib5giQQ8v7q1rL
- Set mod_version to 1.6.6 for release main inherited the alpha-suffixed version (1.6.6-a37) from the merge of v1.20.1, which fails the stale-version check in stage-core-release.yml -- between releases mod_version must be exactly one patch ahead of the last v*.. tag (v1.6.5), with no alpha suffix.
Projects on Modrinth are automatically available through a Maven repository for use with JVM build tools such as Gradle. To learn more about the Modrinth Maven API, click here.
Note: When available, you should use the creator's maven repo instead as it will have transitive dependency information that the Modrinth Maven API does not. You may also end up with duplicate dependencies if you use a mix of Modrinth and non-Modrinth Maven repositories for your dependencies, because the group identifier will be different when served through the Modrinth Maven API.
Maven coordinates:
Version ID:
build.gradle:
repositories {
exclusiveContent {
forRepository {
maven {
name = "Modrinth"
url = "https://api.modrinth.com/maven"
}
}
// forRepositories(fg.repository) // Uncomment when using ForgeGradle
filter {
includeGroup "maven.modrinth"
}
}
}
// Standard Gradle dependency
dependencies {
implementation "maven.modrinth:X8IXdS40:UjoIFDMO"
}
// Legacy Loom dependency
dependencies {
modImplementation "maven.modrinth:X8IXdS40:UjoIFDMO"
}

