stonecutter based rewrite to better support multiversioning - #93
stonecutter based rewrite to better support multiversioning#93AlmanaX-21 wants to merge 48 commits into
Conversation
1.21.1 ItemRenderer reads alpha from the item colour handler (FastColor.ARGB32.alpha). The handler returned 24-bit RGB, so alpha was 0 and the wrench rendered fully transparent. 1.20.1 hardcodes alpha to 1.0F and 26.1.2 uses ARGB.opaque, so both were unaffected.
The Stonecutter conversion copied whole source trees into versions/1.21.1-neoforge and versions/1.20.1-forge, shadowing the root src per file. 172 of those overrides (25 Java, 116 PNG, 22 MD, 9 JSON) were byte-for-byte identical to their root counterpart, so each target still inherits the same file after removal. No build output changes.
The 1.20.1 tree used `Logisticsnetworks` while 26.1.2 and 1.21.1 use `LogisticsNetworks`. This case-only difference blocked those files from being shared from root src. Rename the class and its 152 references across 71 files; no behaviour change.
26.x renamed ResourceLocation to Identifier. Rather than keep a per-target override for every file that only differed by that token, add a global `replacements.string(current.parsed < "26")` rule that rewrites Identifier back to ResourceLocation for the legacy targets. The token mapping is exactly 1:1, so this retires 45 override files (44 on 1.21.1, 1 on 1.20.1) that now inherit from root src.
Filters become virtual on 1.21.1, matching 26.1.2: the filter items remain registered as NBT carriers but are unobtainable, and filters are conjured on demand instead of crafted and slotted. - NodeMenu: drop the 3x3 FilterSlot grid (upgrades only) - NodeScreen: virtual filter buttons + SMALL/MOD/NAME picker popup - OpenNodeFilterPayload: 4-arg with VirtualFilterType; handler now materialises a filter instead of rejecting empty slots - AddNodeFilterItemPayload + handler: drag an item onto a button to create a filter; FilterItemData.addItem added - ChannelData.FILTER_SIZE 9 -> 6 with placeOverflowFilters migration so existing saves relocate slots 6-8 instead of losing them - retire the 5 standalone sub-filter items (kept registered but inert to avoid deleting existing player stacks); rewire TransferSlotAccess and TransferAmountRules to the per-entry model - creative tab excludes filter items; filter recipes removed; FILTERS tag cut to 5 entries; picker/hint lang keys added
Same virtual-filter conversion as 1.21.1, adapted to the 1.20.1 Forge idioms (hand-rolled network/codec + network/payload shims, ItemStackCompat, NetworkHandler registration, inline slot-access in TransferEngine). - NodeMenu: drop the 3x3 FilterSlot grid (upgrades only) - NodeScreen: virtual filter buttons + SMALL/MOD/NAME picker popup - OpenNodeFilterPayload: 4-arg with VirtualFilterType; handler materialises instead of rejecting empty slots - AddNodeFilterItemPayload + handler; FilterItemData.addItem added - ChannelData.FILTER_SIZE 9 -> 6 with placeOverflowFilters migration - retire the 5 sub-filter items (kept registered but inert); rewire the inline slot-access and amount-threshold logic to the per-entry model - creative tab excludes filter items; filter recipes removed; FILTERS tag cut to 5 entries; picker/hint lang keys added
1.20.1 still drew each node as a separate baked crate model. Port the connection-aware geometry from 1.21.1 so adjacent nodes render as one continuous frame that follows the attached block's collision shape. - add client/NodeConnectionMask (verbatim) and client/NodeGeometry (vertex emit adapted to the Forge 1.20.1 VertexConsumer API: vertex/color/uv/overlayCoords/uv2/normal/endVertex, ARGB unpacked) - renderModel now tries renderConnectedModel first, falling back to the baked NodeModel; port getConnectionMask + neighbour/corner bounds matching and the per-tick node lookup from 1.21.1 (level API identical) - add ClientConfig.connectedNodeTextures (default true) to gate it The ModConfigScreen toggle is not wired; the setting is configurable via the config file.
Baseline for the three-target Stonecutter parity work. - Move lang, guides, models, recipes, tags and loot tables into the shared root source set; legacy targets now inherit 94 and 97 of 100 resources. - Port the .lnet network export/import and mass-placement clusters down to 1.21.1 and 1.20.1, with the shared LnetPaths/LnetNbtAccess and MassPlacementInventoryAccess/MassPlacementNetworkAccess seams. - Re-enable datagen on both legacy targets and commit the generated output. - Add the iris (1.21.1) and emi/oculus (1.20.1) dependencies. - Add LnetNetworkFile, NameFilterValidation and NbtRuleMatcher tests to the shared test source set. - Ignore versions/*/logs.
…ules
The 1.20.1 tree already carried a hand-rolled 1.21-API compat layer, but every
file that used it had to be duplicated purely to swap import lines. Express
those swaps as global replacement rules instead, so the root file is inherited
unchanged.
- Add network/dist/{PacketDistributor,ClientPacketDistributor} shims: 1.20.1
delegates to NetworkHandler, 1.21.1 to NeoForge's combined PacketDistributor
(26.x split the client half into its own class).
- Add ByteBufCodecs.stringUtf8(int) to the 1.20.1 shim so the bounded
name-filter codec resolves there too.
- New rules: the four vanilla payload/codec types, IPayloadContext, both packet
distributors, and the four loader packages that differ only by namespace.
Retires 24 override files. Verified: the 26.1.2 jar is MD5-identical, and on
both legacy jars every retired class is byte-identical to before - the only
changes are the added shim classes and ByteBufCodecs gaining a method.
Twenty-four per-target files diverged from the shared root only by import order, line wrapping, parameter or local names, comments, or member visibility - none of it version-specific. Delete them and inherit root. Also adds the FMLPaths loader-package rule, which retires LnetPaths. Two of these carry a deliberate behavioural fix rather than pure cosmetics: SetNameFilterPayload now uses root's length-bounded name codec on both legacy targets instead of the unbounded one. Verified: all three jars keep an identical class list apart from the shims added in the previous commit, and the tests pass on every target. Java inherited from root: 1.21.1 83 -> 91, 1.20.1 18 -> 60.
NameMatchScope had been collapsed to a NAME-only stub on 26.1.2, which silently disabled matching against an item's tooltip lines. The rest of the feature survived on that branch - FilterMenu still cycles the scope, FilterScreen still syncs and renders it, and both lang keys are still shipped - so only the enum and the NameFilterData read path were missing. Restore the three scopes in the shared enum, carry the scope through NameFilterView, and apply it in containsName. The 1.20.1 tooltip signature takes no TooltipContext and needs the dedicated-server guard, so that call is the first Stonecutter conditional in the tree; FMLEnvironment joins the loader packages handled by replacement rules. Also confirms two apparent legacy-only features are not features: the nine extra ThemePaint helpers have no callers, and the AE2 loose-match sourcing path exists only to satisfy clipboard requirements for physical filter items, which the virtual filter model removed.
26.x reworked the CompoundTag getters into Optional-returning methods plus an *Or family, and 1.20.1 has no data components at all. Between them these two API changes account for ~170 call sites across the 14 largest shared classes, and they are the main reason the filter, data and entity packages still cannot be shared. Introduce util/NbtAccess and util/ItemDataUtil, both single shared files with Stonecutter conditionals, and route DurabilityFilterData through them as the first consumer. ItemDataUtil keeps 1.20.1's existing nested ln_custom_data layout, so stored data is read back unchanged. DurabilityFilterData is now inherited on both legacy targets. Its isDurabilityFilterItem already returns false on 26.1.2, so the durability sub-filter goes inert there too, which is the intended virtual-filter behaviour. Java inherited from root: 1.21.1 91 -> 94, 1.20.1 60 -> 62.
NameMatchScope, Themes, laptop.json and the 1.21.1 mixin config were line-identical or brace-style-only variants of the root files.
…gets 26.x removed CompoundTag.putUUID/getUUID, so NbtAccess grows putUuid / getUuidOrNull / getUuidOrRandom and each target keeps its own on-disk UUID shape - a dashed string on 26.x, the four-int array elsewhere. Existing saves still read back on every target. Behavioural reconciliation, 26.1.2 canonical: - 1.20.1 gains NodeRef.priority plus the import-priority sort, the dimensional/tier caches, the view cache and the sorted node list. - both legacy targets adopt the 10-game-tick transfer-visual topology cadence in place of their 20-server-tick one. - rebuildCache now walks the sorted node list rather than the unordered set, so equal-priority ordering is stable across reloads. This came from the 1.21.1 branch, which was ahead of 26.1.2 here. NetworkScheduler carries the first forge/neoforge tick-event directive; ServerLifecycleHooks joins the loader-package replacement rules.
Both legacy targets shipped lower per-tier limits (stack/transfer caps at 16/1k, 32/5k, 64/20k, 10000/1M against 26.1.2's 32/10k, 64/100k, 256/1M, 10000/2.1G) and logged config load failures without the Config.debugMode gate. Deleting the overrides adopts the canonical file for both. Existing upgrades.json files on disk are untouched; this only moves the defaults. The netherite upgrade texture overrides were 16x16 stills shadowing the canonical 8-frame 16x128 strip, whose .mcmeta both targets already inherited, so legacy silently lost the animation.
26.1.2 replaced the standalone amount/durability/nbt/slot/tag filter items with per-entry fields on FilterItemData.ItemFilterSlot. Both legacy targets still registered all five as deprecated-tooltipped carriers. Their registry entries, creative-tab exclusions and ten orphan models/textures are gone; the item and data classes stay so the FilterMenu and FilterLogic branches that name them keep compiling. Nothing constructs them any more, so every instanceof check is now permanently false, matching 26.1.2 behaviour. SAVE-AFFECTING: vanilla drops stacks of these five from existing 1.21.1 and 1.20.1 worlds on load. This is what registry parity with 26.1.2 means and was confirmed with the owner. Also brings two values to canonical: filter capacities on legacy were 9/18/27 against 26.1.2's 45/45/45, and the 1.20.1 logistics node entity was sized 1.0 instead of 0.05.
…arget The screens were already written against the pre-26 render/renderBg/ renderLabels shape and adapted forward by LegacyContainerScreen, but the adapters themselves lived only on 26.1.2 and both legacy targets stubbed them out and re-implemented every screen. They are now single shared files carrying the version split internally: - LegacyContainerScreen and the new LegacyScreen collapse to little more than the vanilla class plus constructors below 26, where render/ renderBg/renderLabels/renderTooltip and the raw input arguments are already the native shape. - ClientInput turns from a 26.x event-record factory into a dispatch seam: keyPressed/charTyped/mouseClicked/widget forward to a child widget in whichever form the target version expects. 51 call sites across seven screens converted. - client.GuiGraphics is replacement-mapped to vanilla GuiGraphics below 26, since the wrapper deliberately mirrors the vanilla method set. fillGradient and renderComponentTooltip added to complete it. ModConfigScreen and WrenchColorScreen move onto LegacyScreen and off the raw GuiGraphicsExtractor; FlatEditBox and FilterScreen's tooltip filter route through the shared hooks. No behaviour change on any target.
FlatEditBox, MassPlacementScreen, ClipboardScreen, PatternSetterScreen, ModConfigScreen and WrenchColorScreen now compile from the common source on 26.1.2, 1.21.1 and 1.20.1. Three genuine API gaps needed directives: - 1.20.1 EditBox.moveCursorTo has no extend-selection overload, so shift-click anchoring is emulated through setHighlightPos. That behaviour did not exist on 1.20.1 before; it now matches 26.1.2. - 1.20.1 mouseScrolled predates the split scroll axes. Absorbed once in LegacyContainerScreen plus a ClientInput.mouseScrolled dispatch, so no screen carries the difference. - 26.x dropped RenderSystem.setShaderColor in favour of a tinted blit, so the wrench colour preview keeps each version's proven draw path, and the gamemaster permission check keeps hasPermissions(2) below 26. 1.20.1 ClientConfig.SPEC becomes public to match the canonical file.
…itor ThemePaint and ThemeState needed no directives at all - their 433-line apparent divergence was entirely the GuiGraphics wrapper type plus nine helpers with no callers, both now handled by the replacement rule. New seams, each replacing a per-screen difference: - ClientInput.altDown/shiftDown: 26.x has no Screen.hasAltDown, so NodeScreen carried private InputConstants helpers that clashed with the inherited statics below 26. - BuiltInRegistries.ITEM/FLUID.getValue -> get replacement rule for the 26.x registry lookup rename, nine call sites. - The remaining widget draw calls route through ClientInput.widget, and NodeScreen switches to renderComponentTooltip, which is what both legacy targets already called at that site. PARITY FIX: SyncNetworkListPayload.NetworkEntry gains createdAt on both legacy targets, which had shipped the record without it - so the node screen's oldest-first and newest-first network sorts had nothing to sort on. The four producing menus now pass net.getCreatedAt(). FilterScreen stays per-target: it reaches past the seam into the fluid APIs (neoforge.transfer.fluid vs neoforge.fluids), the sprite package and MultiLineEditBox.builder, none of which the shared layer covers yet.
appendHoverText differs three ways: 26.x passes a TooltipDisplay and a Consumer, 1.21.1 a TooltipContext and a List, and 1.20.1 a nullable Level and a List. Each item now declares all three under mutually exclusive conditions and funnels into one appendLines(Consumer) body, so the tooltip text itself lives once.
|
Important Review skippedToo many files! This PR contains 255 files, which is 155 over the limit of 100. To get a review, reduce the PR to 100 files or fewer by splitting it into smaller PRs or changing its base branch. Upgrade to a paid plan to raise the limit. This review couldn't start because sufficient usage credits or metered capacity aren't available. Add credits or update usage-based reviews in the billing tab, then retry. ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: ⛔ Files ignored due to path filters (133)
📒 Files selected for processing (255)
You can disable this status message by setting the Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
26.1.2 sets the node's colour from its network in four places; the 1.20.1 and 1.21.1 copies of ServerPayloadHandler and NodeClipboardConfig only kept the one in handleSetNetworkColor. Assigning a node to a network therefore left NETWORK_COLOR at its default, so the node stayed white until a chunk reload let EventHandler.onEntityJoinLevel resync it.
NetworkRegistry.load on 26.1.2 flags networks whose NBT carries no Color tag and marks the registry dirty, so the colour rolled by the LogisticsNetwork field initialiser is written back. Both legacy copies omitted that, so a save predating the colour feature re-rolled every network's colour on each world load instead of keeping the first one.
On 26.1.2 LegacyContainerScreen calls render() after vanilla has already drawn, so the screen's render() is a post-draw overlay hook and must not call super.render. Below 26 that class collapses to AbstractContainerScreen and render() is the draw entry point, so the per-target copies skipped renderBg, the slots, the items and the widgets entirely: the filter page was invisible while its hitboxes and its own tooltips still worked. Dispatch to super.render again, passing -1/-1 while a tag or NBT sub-mode is open so the vanilla slot hover stays suppressed, and give the detail page its own background and renderBg pass. The clipboard tooltip now runs after the draw chain rather than returning ahead of it, which is what blanked the whole GUI while hovering a clipboard button.
The reposition tick used Vec3.atCenterOf, which returns y+0.5, so nodes floated half a block above the block they wrap. 26.1.2 and 1.20.1 both use atBottomCenterOf here and their renderers carry identical pose translations, so nothing downstream was compensating. This also realigns the shared TransferVisuals beams, which already drew from atBottomCenterOf.
ModConfigScreen draws its panel first and calls renderSuper last so its buttons land on top. Below 26 that reaches Screen.render, which applies the menu blur before drawing widgets, so the blur fell over the finished panel while the buttons and edit-box values stayed sharp. Both shipped legacy branches blanked renderBackground for this; restore it per target, since the signature gained mouse and partial-tick arguments in 1.21.
The mixin config was declared on 26.1.2 only: NeoForge 1.21.1 had the [[mixins]] block commented out and Forge 1.20.1 never set the MixinConfigs manifest attribute, so GuideItemMixin never applied there. Declare it on both, and fold the two per-target copies into the root file behind a stonecutter branch for the pre-26 getCreatorModId signature, which takes no HolderLookup.Provider.
…et NBT access NodeConnectionMask, JsonModelLoader and LnetNbtAccess existed as near-identical copies under both legacy targets. Promote one of each to the root source set and delete the duplicates, with the remaining version differences carried by stonecutter branches. ModRenderTypes picks up the two lines the shared loader needs on 1.20.1.
…red item The five physical sub-filters kept a per-target item, data class and set of payloads on both legacy targets, duplicating what 26.1.2 already expresses through the virtual filter model. Replace them with a shared LegacyFilterItem carrying a Kind enum and a shared LegacyFilterData that converts stored settings to the canonical ln_filter root on read, so the historical item IDs stay resolvable and existing stacks keep working. Deleting the superseded payloads brings every target to the same 52 active registrations, which build.yml now asserts alongside the absence of the retired classes and the presence of the legacy item models. Datagen output is regenerated to match, and the 1.20.1 payload records that had drifted into per-target copies now come from the root set.
Note the 52-payload protocol, the hidden historical filter IDs whose stored settings convert to canonical virtual filters, and GuideME mixin support on NeoForge 1.21.1 and Forge 1.20.1.
No description provided.