Repository navigation
Legacy 1.4.7 Estimate
Written 2026-11-06 after the M0 work (corpus, scanner, tables, loader groundwork). Measured numbers are in Legacy-1.4.7-Corpus; the model is the 1.6.4 one (Legacy-1.6.4-Estimate), with 1.5.2 as the version in between. Back to Home, plan in Version-Roadmap.
About 1.5 to 2.5 days of wall-clock time after the 1.5.2 layer loads (the roadmap said 0.5 to 1 day), 3 to 5 agents in parallel, plus or minus 50%. The delta over 1.5.2 is mostly three things the
roadmap did not count: sprite-sheet textures (1.4.7 has no Icon), the ModLoader BaseMod emulation (27% of the corpus touches it) and the notch-name dependence (96% of the jars are obfuscated). Everything else (numeric
ids, @NetworkMod, tick handlers, player trackers, Packet250CustomPayload) is the 1.6.4 work and is shared. M0 took about 2 hours.
| Area | 1.4.7 | Work |
|---|---|---|
| Names in the jars | notch (obfuscated) names in 96% of the jars (yc, members a, b); the dev sources used flat net.minecraft.src.<Name> (MCP 6.x), the last Forge builds (6.6.2.5xx) already the packaged MCP 7 names, and 20% of the jars mix notch with packaged descriptors |
Done in M0: legacy/1.4.7/notch.txt (notch to flat MCP/SRG names, from the client jar and joined.srg), forward/1.4.7/flat-names.tsv (1,339 flat classes to their 1.5.2 packages), ForwardRenames.flat, the member lookups walk the flat hierarchy and compare packaged table keys. Open: NotchNames misses about 5% of member references (mod overrides called through a vanilla owner), closed in M1 |
| Version detection | no class-name markers: 1.4.7 shares @PreInit/ISidedInventory/ForgeSubscribe with 1.5.2 and 1.6.4 |
Done: a per-version fingerprint of the obfuscated member references (right version 90 to 100%, wrong ones 0 to 50%), 1.4.7-only FML classes, flat names, declared version, file name; the existing 1.5.2/1.6.4/1.7.10/1.12.2 detection is unchanged (checked on 162 jars) |
| Packaging |
.zip is 34% of the mods, ModLoader mods have no @Mod and no mcmod.info |
Done: mods/1.4.7/ folder (zips accepted there), BaseMod subclasses become mod declarations (LegacyModDecl.modLoader) |
| Textures | integer indices into sprite sheets; see below | the largest new item, 1 to 1.5 days |
| ModLoader |
BaseMod, ModLoader.registerBlock/addName/addRecipe/addShapedRecipe/registerEntityID/addOverride/getUniqueSpriteIndex/registerTileEntity, MLProp, IBlockRender... as default-package classes of a reobfuscated jar |
hand-written shim (about 600 to 900 lines; FML's ModLoaderModContainer semantics: load(), modsLoaded(), addRenderer, takenFromCrafting...), 3 to 4 hours |
| Lifecycle |
@PreInit/@Init/@PostInit in 81% of the jars (no @EventHandler) |
shared with 1.5.2 |
| Numeric ids, network, ticks, trackers | as 1.6.4 (51 of 65 jars use ids; 43 @NetworkMod; 27 tick handlers) |
shared with 1.6.4/1.5.2: this is their M1/M2 |
| Liquids |
net.minecraftforge.liquids.* (LiquidStack(itemID, amount, meta), ITankContainer, LiquidContainerRegistry) in 13 jars (20%) |
adapter onto fluids (FluidStack, IFluidHandler, capabilities); also used by the 1.5.2 and 1.6.x mods, so it pays three times; 3 to 5 hours |
| Small deltas |
RenderEngine (37 jars), AABBPool/Vec3Pool (20/12), ISidedInventory (Forge's own, 18), IArmorTextureProvider (8), SoundPool (7), TexturePackList/ITexturePack (8/7), IClassTransformer coremods (10), StepSound... |
RenderEngine and the pools are 1.5.2/1.6.4 items; ISidedInventory and the armor provider are a capability adapter and a texture hook; sounds need a SoundPool facade |
| Jar-mod style | Better Than Wolves (and its add-ons) replace vanilla classes | out of scope, as in every version |
The 1.5.2 layer already has to turn string texture paths into ResourceLocations (the RenderEngine.bindTexture(String) family, 37 of 65 jars here), and 1.6.4 has Icons that the shim maps onto IIcon. 1.4.7 needs both of those plus
index-based textures. What the measurements say about size (corpus): 41 of 65 jars (63%) use Forge's per-block texture file, 22 (33%) set blockIndexInTexture/iconIndex/setIconIndex
by hand, 19 (29%) name the vanilla sheets terrain.png/gui/items.png, 42 reference at least one 256x256 sheet (255 sheets in total, 248 of them 256x256 with a 16-pixel grid), only 3 register animated textures.
Design (all native, no side channels):
-
A sheet registry in the loader's asset step. For each sheet PNG a mod ships (found by the string constants and
setTextureFile/preloadTexturearguments, the same scan this corpus uses; the 256x256 grid is assumed), the pack generator cuts the 256 tiles lazily and writes them as individual spriteslegacy147/<mod>/<sheet>/<index>into the generated resource pack, so the vanilla atlas stitches them like any other texture (animations: one.png.mcmetaper tile where a TextureFX updates it, a later item). Cutting only the indices the code can reach would need data-flow analysis; cutting the full 16x16 grid is cheap (a few hundred 16x16 sprites per sheet), and empty (fully transparent) tiles are skipped. -
Index to
IIconin the shim.Block.blockIndexInTexture,Block.getBlockTextureFromSideAndMetadata,Item.iconIndex,Item.getIconFromDamagereturn ints; the shim'sgetIcon(side, meta)wraps them:(textureFile(), index)to the registered sprite.textureFile()defaults to/terrain.pngor/gui/items.png,setTextureFileandITextureProvider.getTextureFile()override it. Mods that override the int methods keep working; mods that overridegetIcondo not exist in this era. -
The vanilla sheets. Indices into
terrain.pngandgui/items.pngthat a mod uses (copying the look of stone, planks, iron ingots) need a 256-entry table index to 1.21 sprite name each (about 500 entries, data; derived from the 1.4.7TextureMaplayout, a few hours).ModLoader.addOverride("/terrain.png", file)andgetUniqueSpriteIndexallocate free slots in the vanilla sheets: the registry hands out virtual indices above 255 and maps them to the override file. -
Whole-image textures (mobs, GUIs, armor, tile entity renderers:
bindTexture("/mods/x/gui.png"), "/gfx/..." paths) go through the 1.5.2 string-path resolver; 1.4.7 only adds the leading-slash resource roots (/gfx/<mod>/,/mods/<mod>/,/mob/,/armor/) and the rule that a mod's file shadows vanilla's of the same path. -
Renderers.
ISimpleBlockRenderingHandlerand tile entity renderers bind sheets and readTessellator.setColorOpaque/addVertexWithUVwith UVs computed from the index ((index % 16) / 16.0): those UVs need the sheet layout of the original sheet, not the atlas. The 1.7.10 shim already rewrites UV math forIIcon; for index-based code the cheap route is to keep the bound sheet as its own texture for tessellator-based rendering (the whole PNG bound to a single texture unit, as FML did) while block/item models use the cut sprites. That is a second path to maintain; 4 to 6 hours.
Total: about 1 to 1.5 days with two agents (the cutter and the index shim; the vanilla index table; the renderer path), most of it after 1.5.2's string-path work is in. This is the main risk: if tessellator-based renderers (BuildCraft pipes, Forestry, RedPower, 20 to 30% of the corpus) need the second path in full, add half a day.
| Milestone | Content | State and estimate |
|---|---|---|
| M0 | Corpus (65 files), scan_147.py, legacy/1.4.7 tables, LegacyVersion.V1_4_7 (forward chain 1.4.7 to 1.5.2 to 1.6.4 to 1.7.10), flat-name relocation, notch-fingerprint detection, mods/1.4.7 + zips, runtime family mapping |
done (this page's date); 64 of 65 jars detect and translate in checkLegacyMod
|
| M1 | Close the notch lookup gap (5%), member forwards for what the 1.4.7 jars call (4,320 synthesized members over 64 jars: the id family, registerBlock, Item.setItemName...), BaseMod/ModLoader emulation, liquids adapter, load without sprite sheets (blocks and items register with a placeholder) |
4 to 6 hours; the server test boots the corpus subset |
| M2 | Sprite-sheet registry + index shim + vanilla index table, string-path textures, ISidedInventory/armor provider hooks, entities and world generation as in 1.5.2 |
1 to 1.5 days; first mods rendering |
| M3 | Client verification (BuildCraft pipes, RedPower, Forestry bees, Twilight Forest, Mystcraft), sounds, GUIs | 0.5 to 1 day, in parallel with M2 |
So 1.4.7 is playable-tier roughly 1.5 to 2.5 days after 1.5.2; with the 1.6.4 and 1.5.2 estimates the 0.4.0 milestone stays at 4 to 5 days (the roadmap said 3 to 4, range 2 to 5; sprite sheets and ModLoader move it to the upper half).
- The 1.5.2 forward tables (
forward/1.5.2/*: EntityLiving/EntityLivingBase, the 1.5.2 to 1.6.4 class and member deltas, string-path textures) are not written yet; 1.4.7 currently falls back to the 1.6.4 tables only, which is what the synthesized-member numbers measure. -
BaseMod/ModLoaderdoes not exist in the shim: the inspector finds ModLoader mods, but they would be linked against empty synthesized classes (6 pure ModLoader jars of 65, 18 using theModLoaderclass). - Sprite sheets (above) for anything that renders; until then blocks and items would have no textures.
- The 5% of unresolved notch members (
TileEntity.a...), best fixed inNotchNamesby resolving overrides through the jar's own class hierarchy for 1.4.7 as well. - The missing corpus core: IC2, Railcraft, Thermal Expansion, Thaumcraft 3, EE, Natura, Tinkers' Construct, Mo' Creatures, Biomes O' Plenty are not obtainable (no 1.4.7 file reachable). Hexxit/Tekkit-style content (the tech trio plus Thaumcraft) cannot be tested; BuildCraft 3.4, Forestry 2, RedPower 2, Applied Energistics and Twilight Forest are the substitutes.
- No game run was done in M0 (no instances were started): everything above is offline link/translation evidence, not runtime evidence.
- Coremods:
IClassTransformer-style plugins (CodeChickenCore and 9 more jars here) depend on the coremod API work done in parallel for 1.6.4/1.5.2.
- Value: 1.4.7 has the smallest pool of the three old numeric-id versions (about 175 to 410 mods, see the roadmap evidence) and many of its mods have 1.5.2/1.6.4/1.7.10 versions; what exists only here is mostly the Hexxit/Tekkit Lite/Feed The Beast Classic-era tech mods and ModLoader mods. Kept because it is a cheap delta and because the notch-name and sprite-sheet machinery is what 1.2.5 (the next ModLoader-era target) needs too.
- Sprite sheets and tessellator UVs are the one place where this version can be much more work than the rest (see the 4 to 6 hour renderer path above).
- Detection of tiny jars (a few hundred bytes, no obfuscated member references) relies on declared versions and the file name; one corpus jar (hopper-1.0.jar) is still not recognised.
-
Shared maintenance:
ForwardRenames.flatis the only 1.4.7-specific hook in the shared remapper path; everything else is data or reuses the 1.6.4 classes.
Server loads of the corpus in batches (./gradlew runServerSubTest, mods in run-subtest/mods/1.4.7) and one client session (Applied Energistics rv9 and RedPower 2, with Sodium, Iris and shaders):
-
Loads and runs (no mod failed): ModLoader mods (
mod_SprintKey,mod_Gibbing, Entity Detector, CCTV), Hats, Portal Gun, Gravity Gun, Dragon Mounts, More Swords, Grimoire of Gaia (48 mobs alive), Resource Engineering, BiblioCraft, Custom NPCs, CameraCraft, Extra Buttons, RedPower 2 (all ten modules), Applied Energistics, Mystcraft, Factorization, ComputerCraft, MiscPeripherals, BuildCraft, Forestry, Twilight Forest (dimension generates). Per-mod ratings are indocs/data/mods.json(source "client"). -
Sprite sheets work for the main sheets: tiles are cut by
SheetCutter, a sheet that code names without its folder (GfxPath("block.png")) is found by file name, and an index-based block or item now wins over the icon a defaultregisterIconswould register (that placeholder hid every index texture of the item sheet). AE's quartz tools and ore draw correctly in the client. -
Fixed this round: a default-package mod class (ModLoader
mod_X) kept two private roots; items a numeric-id mod never registers are registered (More Swords); constructor adaptation casts narrowed parameters instead of passing null (AI task owners: every Grimoire mob failed to tick); notch member lookup through packaged Forge interfaces (ISidedInventoryimplementors kept notch method names); one synthesized name per class (flat and packagedTextureFXwere two classes, aVerifyErrorfor RedPower's animated textures);BiomeCacheBlock(Twilight Forest chunk generation); the home area onEntityLiving(ghasts). -
Open: RedPower's own sheets (
worlditems1.png,base1.png) are cut but its items name tiles through a path the layer does not read yet (iconIndexstays -1), tessellator renderers (RedPower multipart, AE cables) are untested, texture animations (TextureFXManager) link but do nothing, the liquids API adapter is not written,@PreInit/@Init/@PostInitwork (every mod above uses them), Mystcraft's age dimensions, Forestry/Binnie's duplicate genetics API classes, Immibis' mods need IC2/ComputerCraft present. - What blocks "supported": the open items above plus client verification of GUIs for more than one mod; the corpus has no IC2, Railcraft, Thermal Expansion or Thaumcraft 3.
Verified in a real client (Sodium, Iris, Complementary shaders; RedPower 2 all modules in the Core/Digital/Mechanical/Compat zips, Applied Energistics rv9, BuildCraft, ComputerCraft, MiscPeripherals, Entity Detector, CCTV, Old Vein Miner, Block Helper, Hopper, rpcDrive); screenshots in docs/screenshots/old-versions/1.4.7.
-
Item textures of RedPower: the cause was not an unread path. RedPower's tools call
Item.setIconCoord(column, row), which the shim lacked (a synthesized no-op), soiconIndexstayed -1;ItemParts-style items (getIconFromDamage(int)overrides) already worked through the bridge.setIconCoordis now a real method; all RedPower items draw. -
Tessellator and multipart renderers: three defects hid every RedPower block drawn by its own handler.
RenderBlocks.overrideBlockTextureis anint(-1 = none) in 1.4.7 and anIIconin 1.7.10, so the mod's first check (>= 0, draw nothing) always passed; reads of it now go throughmcc$overrideIndex()(member-manualGrule). A handler that binds a sprite sheet per part while the Tessellator is drawing (Forge 1.4.7 drew the pending vertices with the old texture before binding) now flushes onbindTexture(String)while a block is captured, and each captured quad remembers the sheet it was drawn under;IsbrhQuadsmaps its tile-position UVs to the cut tiles of the atlas (vanilla/terrain.pnggoes through the 256-entry table).ISimpleBlockRenderingHandler.shouldRender3DInInventory()lost its argument in 1.7 (bridge rule added, 1.6.4 table, so it also helps 1.6.4 handlers): block items now show their 3D icons. -
GUIs: images are bound by
getTexture(path)ids; the id is mapped back to the location (the draw code names textures through the render context), so the alloy furnace and deployer GUIs draw. Container slots and clicks sync (items moved into both machines). -
Other generic fixes: boolean
isProvidingWeakPower/StrongPowerbridge (1.4.7 returned a boolean),Block.getBlockTextureFromSideAndMetadata,isDefaultTexture,getBlockBrightness, vanilla blocks'/terrain.pngindex for covers,EntityPickupFX(ComputerCraft's turtle client failed verification),EntityLivingBase.getDropItemId(reflection by name), dirty marks from the server thread no longer assert in Sodium,Synth.dispatchsurvives a tile class that mentions an absent optional API (a MiscPeripherals tile crashed the world tick on IC2'sic2.api.Direction), and the sheet cutter also cuts a mod's own 256x256blocks.png/items.pngby name (BuildCraft builds those paths at run time). -
Liquids:
net.minecraftforge.liquidsresolves to the 1.6.4 shim (fluid capability adapter) through the forward chain; BuildCraft 3.4.6 links; not exercised at run time. -
Still open: texture animations (
TextureFXManager: RedPower'sTextureAnimFX, water/lava tiles of mods) link but do nothing; AE cables placed through the item path and AE GUIs were not tried; survival use of wires and gates (power, logic) and RedPower world generation untried; the RedPower Mining module is not in the corpus; Forestry/Binnie duplicate genetics API; Better Than Wolves is a modified-game jar mod (see below). - What blocks "supported": animations, a survival session of the RedPower flagship (wire, gate, machine chains; ore generation), GUIs of AE, (the BuildCraft block sheets are cut now and draw). Rating: RedPower works, Entity Detector works, BuildCraft works, AE partial, ComputerCraft partial, CCTV and MiscPeripherals loads.
-
Better Than Wolves 4.65b (old-only, a modified-game jar mod): the loader translates it (475 classes, 253 synthesized API classes for the vanilla classes it replaces, 3 unresolved references) and discovers
mod_FCBetterThanWolves, but construction fails withClassNotFoundException: mod_FCBetterThanWolves. It replaces vanilla classes (mobs, blocks, world generation) rather than adding to them, which the shim cannot express; it would need the vanilla-class-replacement semantics of a patchedminecraft.jar(the replaced classes loaded in place of the game's) or a rewrite of its changes as hooks. Not near working; no time spent beyond this check.
-
Texture animations work.
TextureFX,FMLTextureFX,ITextureFXandTextureFXManagerare now real shim classes (v1_6_4 layer, the forward names of the flat 1.4.7 classes) instead of synthesized stubs;ModLoader.addAnimation,TextureFXManager.addAnimationandRenderEngine.registerTextureFXregister intoAnimations147. Each client tick it calls the mod'sonTick(), finds the sheet by lettingbindImagerun against the shim's engine (it records the path ofbindTexture/getTexture), maps (sheet,iconIndex) to the cut sprite throughSpriteSheets147and uploadsimageData(RGBA, any tile size, with box-filtered mip levels) into the sprite's place in the block atlas. Needed on the loader side: a jar that has aTextureFXsubclass also gets its blank sheet tiles cut (the animation draws into tiles that are empty in the sheet). Verified in the client: RedPower's twoTextureAnimFXtiles and BuildCraft's oil/fuel effects upload every tick without errors. Not verified visually: which RedPower block shows the animation, and BuildCraft's oil blocks (they render as a hole; their fluid rendering is a separate gap; still and flowing oil name the same tile because the block never setsblockIndexInTexture, which the layer reads as 0). -
Minecraft.texturePackList/RenderEngine.texturePack(default pack, files read from the mods' class path): RedPower's animation reads its frames throughgetSelectedTexturePack().getResourceAsStream(path)and failed in its constructor before. -
StringTranslate.getCurrentLanguage()returns the language code; BuildCraft chooses itslang/buildcraft/<code>.propertiesby it, so its GUI titles are translated now. - RedPower survival: the alloy furnace GUI shift-click moves into its grid, fuel burns, and red alloy comes out; a vanilla lever powers a RedPower lamp. Open: wire and gate chains, deployer/transposer item movement, ore generation in a normal world, pump and tube transport, the project table crafting; BuildCraft's autocrafting table shows no recipe preview; AE GUIs and cables (terminal, drive, controller) and BuildCraft pipes, engines and liquids; Mystcraft ages; Forestry/Extra Bees genetics duplicate; the final corpus load check.
-
Still blocks "supported": the open items of the previous bullet (a survival session of the flagship mods beyond the alloy furnace and lamp, AE and BuildCraft use, a corpus-wide load run with results in
docs/data/mods.json).
Real client (NeoForge 1.21.1, Sodium, Iris, Complementary shaders), survival actions through the item path (items placed and used like a player does; gives by command only):
-
RedPower 2 works in survival. Logic: a lever on the side of a block next to a red alloy wire, a NOT gate and a lamp: the wire carries the signal (power 255 falling by one per block), the gate inverts, the lamp goes dark and lit again. Machines: the transposer moves items from a chest on its back over two pneumatic tubes into a second chest on a redstone pulse; the deployer places blocks from its inventory; the project table crafts (sticks from planks). World generation in a normal world: the eight ores (ruby, emerald, sapphire, silver, tin, copper, tungsten, nikolite) and marble/basalt generate (about 750 ore blocks per chunk of the area scanned, marble about 430); rubber trees were not found in a 14x14 chunk area (untried further). Screenshots in
docs/screenshots/old-versions/1.4.7. -
Causes found this round (all generic):
- A tessellator renderer that only binds a sheet (
RenderLib.bindTexture("/eloraam/wiring/redpower1.png")) never had that sheet cut, so wires drew with a vanilla tile (copper bulb).SheetCutternow also cuts sheets bound inside block/tile renderer classes (names containingRender, notGui). - Redstone: vanilla blocks answered 0 to
isProvidingWeakPower/StrongPower(only blocks of the shim had logic), so no legacy mod could read a lever, button or redstone block. The baseBlocknow reads the modern signal for blocks of the game; the 1.4.7 boolean forms (isProvidingStrongPower(...)Z, a call on a receiver whose class lacks the boolean form) are served by theBlockfacade (legacyconnector/v1_6_4/facade/.../Block); a redirect rule was wrong (it also caughtsupercalls and recursed through the bridge of the mod's own override). -
CraftingManager.findMatchingRecipe(inv, null): the client's project table builds its grid from a tile without a world, so the vanilla recipes (looked up in the modern recipe manager) never matched and the result slot stayed empty on the client. A null world now falls back to the client level (or the server's overworld). -
FurnaceRecipes.smelting().getSmeltingResult(itemId)andgetExperience(itemId)(1.4.7 id forms) were stubs returning null; now served through the id table. (RedPower's alloy furnace does not smelt vanilla ores: that is RedPower's own recipe set, only the Blulectric furnace uses the vanilla list.) - BuildCraft oil:
BlockFluid(id, material)gave the tile 205 (water-like) or 237 (lava-like) of the block's own sheet, which BuildCraft's oil animation draws into; the shim's liquid base class has no tile. Fluid blocks of a flat-name version now get the 205/237 index (loader claim hookIdConstructors,Block.mcc$claimFluidTexture) andBlockLiquid.getIconreads it (sides the next tile).RenderBlocks.renderBlockFluidsisrenderBlockLiquidin the shim (a forward rule; without itRenderingOildrew nothing and oil was a hole). - Scheduling mods (RedPower gates, timers) use
World.getWorldTime(); with the game ruledoDaylightCycleoff (the screenshot test harness default) the day time stands still and gates never fire. Not a layer defect (1.4.7 had no such rule), noted for test setups.
- A tessellator renderer that only binds a sheet (
- BuildCraft: wooden pipe plus wooden engine (powered by a redstone block) pulls items out of a chest and cobblestone pipes carry them to the second chest; the engine finds its receiver on placement (orientation 4 towards the pump) and runs; oil blocks draw (black pool). The pump did not lower its tube into the oil in the time tried (tank empty), so liquid transport is not verified.
- Applied Energistics rv9: controller, cables, drive and terminal place through the item path; the ME Terminal and ME Drive screens open and draw (title, search field, sort buttons; drive cell slots); cables still draw as dark cubes, and without power the network cannot be used, so crafting through an ME network was not reached.
-
Corpus-wide load check (65 files of
test-mods-147, fresh cache, config and world, server port 25906,./gradlew runServerSubTest): every mod loads except Better Than Wolves (patched-game jar) and the two JInput mods (RawInput, XInput:net.java.games.inputis not in the game). The two sprint mods are client-only (they touch client classes, so the dedicated server cannot load them; they load in the client). Ratings are indocs/data/mods.json(source "client", 75 mods: 44 works, 28 loads, 6 partial, 5 fails). Note for test sets: default item ids collide when everything is installed at once with a config left over from an earlier set (RedPower's id 768); a fresh config is clean. -
Forestry and Extra Bees load. Forestry finds its plugins by listing its own jar for
forestry/plugins/Plugin*.class; the shared-package merge moved that package (Extra Bees has copies of the Forestry API and plugin classes) into the shared library and Forestry saw no plugin, so no item existed and the genetics API stayed unset (the "Binnie AlleleManager registry null" symptom: not a second copy of the class, a missing registration). For flat-name (1.4.7) jarsSplitPackageResolvernow keeps a package whose copies are all in such jars in the jar of the mod that owns its root, strips the others, and adds the classes only the others had to the owner's jar. Other versions keep the old behavior. Result: 16 plugins, 330 alleles, 393 Forestry items and 35 blocks. The Forestry screens do not open: this build'sGuiForestryextends the class that isGuiScreenin 1.4.7's mapping (the jar was built against another obfuscation), so it is a corpus limitation. -
Mystcraft loads (a
VerifyErroronnew TextureCompassFX(): the vanilla texture FX classes were synthesized and notTextureFXsubclasses; they are shim classes now) and an age can be created and entered;FMLTextureFX.setup()runs at registration like Forge did (running it in the constructor read fields of the subclass that did not exist yet: Forestry's habitat locator). -
Other generic fixes:
ItemFlintAndSteelshim (CustomNPCs failed in init on the synthesized class), the 1.4.7 misspellingEntityAIMoveTwardsRestrictionmapped to the real class (four Grimoire of Gaia mobs failed verification), an item that never sets an icon index draws tile 0 (CCTV's monitor),CraftingManagerno longer touches client classes from the server (it broke every mod on a dedicated server). -
Still blocks "supported": ComputerCraft's terminal draws white rows (its
FixedWidthFontRenderercompiles the glyph quads into OpenGL display lists withglNewList, built from a font bitmap it uploads itself, so no computer can be used yet), Forestry's screens (corpus build), an Applied Energistics network (power source and cable drawing), the BuildCraft pump (tube did not extend; liquids unverified), rubber trees of RedPower (none found), Better Than Wolves and the JInput mods, the Mystcraft machines (43% of its self-test errors), and the missing corpus core (IC2, Railcraft, Thermal Expansion, Thaumcraft 3). Rating of the version: alpha (RedPower 2, BuildCraft, Entity Detector, CCTV, MiscPeripherals blocks, AE screens work in a real client).
-
ComputerCraft works. The white rows were not a display-list problem (compiled lists, colours and Tessellator draws replay correctly). Two generic causes: (1)
RenderEngine.allocateAndSetupTexture(BufferedImage), whichFixedWidthFontRendereruses to upload the font sheet, was an unimplemented stub returning 0, so the glyph quads sampled no texture. It is now implemented in the shimTextureManager(nearest filtered, repeating); the mod builds the renderer while mods load (no GL context), so the call returns a handle and the image is uploaded when the id is first bound (glBindTextureorbindTexture(int)).glBindTexturealso resolves the handlesgetTexture(path)returns for textures that are not loaded yet. (2) The computer's ROM (lua/rom) is mounted withZipFile.getEntry("lua/rom")on the mod's own jar, and the translated jar had no directory entries (Path doesn't exist inside zip file, the computer never booted).LegacyJarTransformer.writenow writes the folder entries andSplitPackageResolverkeeps them. Checked in a real client with shaders:help,ls, the Lua prompt; a turtle refuels from coal in its slot and moves; a MiscPeripherals block beside a computer is listed as a peripheral. -
Applied Energistics works. The cable block draws through
RenderBlocks.renderBottomFace/TopFace/East/West/North/SouthFace(Block, x, y, z, int tile)(1.4.7 forms taking a tile index of the bound sheet), which were unimplemented stubs, so cables fell back to the generated full cube. They are shim methods now (an icon covering the tile in sheet space while a block is captured, the cut sprite for items). The cable'srenderCableAtalso callsmarkBlockForUpdatefrom the chunk meshing thread, which reachedClientLevel.sendBlockUpdatedand threw in Sodium (the whole renderer failed): from another thread the section rebuild is queued and the level notice skipped. A controller powered by an adjacent wooden BuildCraft engine, a drive with a 1k storage cell and a crafting terminal form a working network: 64 cobblestone put into the C-Terminal stay listed. Open: the ME Access Terminal item (multiblock1 meta 6) does not place (the other terminals do), and a light blue square is drawn on the ground under every cable (not a quad of the block's model: the captured quads are the thin box). -
RedPower world generation. Ores (about 5000 ore and 6000 deepslate-level ore blocks in an area of 129x129 blocks) and marble/basalt generate in a normal world. Rubber trees only generate in jungle biomes (the mod tests
BiomeGenBase.jungleandjungleHills, not forests; earlier forest scans found none): a jungle 2.6 km from spawn had 1735 rubber logs and 2071 leaves. The RedPower pump with tubes was not tried; BuildCraft's pump is unchanged. - Still blocks "supported": Forestry's screens (corpus build), the BuildCraft pump (liquids unverified), the RedPower pump, Better Than Wolves and the JInput mods, the Mystcraft machines, the AE ground square and Access Terminal, the missing corpus core (IC2, Railcraft, Thermal Expansion, Thaumcraft 3), Old Vein Miner and CCTV picture-in-picture not exercised.
What "supported" means for 1.4.7 in 0.4.0: the layer loads 1.4.7 mods (Forge and ModLoader), their blocks, items, entities, recipes, GUIs and world generation work in a real NeoForge 1.21.1 client with Sodium, Iris and shaders, for the flagship mods; mods that need the vanilla game jar replaced or hardware libraries are reported as such. It is alpha, not beta: only a handful of mods were played in survival.
Works in a real client (survival): RedPower 2 (wires, gates, machines, tubes, ore and rubber-tree generation), BuildCraft (pipes, engines, pump and tank with liquids, oil), ComputerCraft (terminal, Lua, turtles), Applied Energistics (powered ME network with controller, cables, drive, crafting terminal, ME Access Terminal), Entity Detector, Twilight Forest (server-side), the corpus of 65 files loads.
Done in this round:
- AE Access Terminal places and opens (it answers "Unable to communicate with controller" without a controller, as in 1.4.7); the earlier "does not place" was not reproduced.
-
The pale square under cables is not geometry: it is not there without shaders, and a 3x3 block of plain vanilla logs placed by
/fillshowed the same square-and-hole look under the shader pack until the section meshed, so it is a shader-pack and chunk-update artifact of fast block changes, not a layer defect. -
BuildCraft pump: water is pumped into a tank (1000 mB). Two causes of the earlier failure, neither a layer defect: the harness has
doDaylightCycleoff (the pump only searches every 100 world ticks of the clock) and the test world's floor is below y=0 (the pump loopsfor (y = pumpY - 1; y > 0; y--); legacy mods assume y >= 0, so liquids below y=0 are not found). -
CCTV monitor now places and draws:
Direction.vineGrowth(the side-to-direction table) was missing, a hanging entity of a mod was checked with the wrong, square box (always overlapping the wall),EntityHanging.xPosition/yPosition/zPositionwere not the shim's fields (the spawn data wrote zeros), and spawn data written with Guava'sByteArrayDataOutput(Forge for 1.6.4 and older) now goes through the old method form (it was anAbstractMethodError; this helps every old mod with a spawn-data entity). -
Old Vein Miner loads; the key and left-click events arrive (the test harness has a
forcekeyverb forKeyboard.isKeyDown), but the mod reaches the game only through reflection on method names (World.getBlockIdand so on) that the layer offers to compiled code but not to reflection, so no vein is mined. Partial. - Mystcraft writing desk screen opens; Entity Detector drives a lamp.
-
Plain failure reports: Better Than Wolves is reported as "does not start: patched-game jar mod", RawInput and XInput as "needs LWJGL joystick libs (JInput)" (log,
docs/data/mods.json).
What does not work or is untested: RedPower pump with fluid pipes (needs a Blulectric power chain; untested), CCTV camera feed (monitor shows no camera; the camera block uses a placeholder tile), Forestry screens (the corpus build's GUI base class is another obfuscation), Mystcraft ages beyond creation, texture-pack-dependent items, Better Than Wolves, the JInput mods, and every mod of the missing corpus core (IC2, Railcraft, Thermal Expansion, Thaumcraft 3, Mo' Creatures). Test-world note: liquids and anything that scans downward fail below y=0.
-
The pale-blue square under RedPower tubes and AE cables was a layer defect, not a shader artifact (the earlier "a 3x3 of logs gave the same look" was never reproduced). Test matrix in a real client: it shows with shaders and without, with Sodium alone it is absent, with Sodium plus MoreCulling it appears, with no performance mods it is absent; vanilla blocks placed the same way (hopper, chest, glass pane, slab) never made it. Cause: MoreCulling reads which faces a block covers from the first model of the state, the generated cube the block handler's model wraps (
IsbrhBlockModel), so the tube counted as an opaque full cube and the ground's top face was culled (the hole shows the sky). Fix: for blocks drawn by a handler that are not full cubes (IsbrhBlockModel.Open) the twoBakedOpacitymethods MoreCulling's mixin puts onBakedModelWrapperanswer "no culling shape, no quads on any side, translucent" (state setters by reflection, no dependency). -
BuildCraft pipes drew as flat lilac boxes: the pipe renderer binds the mod's sheet and draws with
RenderBlocks.renderStandardBlock, whose icons are atlas sprites, andIsbrhQuadsread their atlas UVs as positions in the bound sheet, so each quad landed on an arbitrary tile (an unused lilac one for most). While a sheet is bound and a block is captured the icon of a cut tile is now the same tile in sheet space (RenderBlocks.mcc$inSheet). The face renderers that take a tile index (renderBottomFace(..., tile), used by the pipe item renderer) fall back to the block's own sheet when none is bound. Open: pipe items in the hand and hotbar draw dark (transparent pipe tiles drawn without a cut-out layer); two item pipes next to each other show a gap in one place. -
RedPower tubes do connect to chests: RedPower's test is
getBlockTileEntity(x,y,z) instanceof IInventory; the layer's view of a vanilla chest implements it (TubeLib.getConnectionsof a tube between two chests returns the west and east bits), and a transposer moved items from one chest through two tubes into the other (1 cobblestone per pulse). The "tube stops short" look was the hole plus the chest model's own 1/16 inset. No change needed.
Offline probe over test-mods-147 / test-mods-152: synthesized members 314 -> 288 (1.4.7) and 209 -> 198 (1.5.2), no new stubs, no verify failures. Done: constructor
adapters (EntityPlayerMP with a name, EntityAITempt with an item id and float speed, InventoryBasic(name, slots), Property()), call adapters (Forward152:
PathNavigate.tryMoveToEntityLiving(entity, float), World.getAllCollidingBoundingBoxes, static BlockPistonBase.determineOrientation, FMLRelaunchLog.getLogger()
as a java.util.logging logger), EntityMinecart.minecartType reads getMinecartType(), Block.getBlockTextureFromSide / getBlockTexture(access, x, y, z, side) redirected
again through the re-entry guarded Redirects147, WorldGenerator.setBlock(world, x, y, z, id), TileEntitySkull.getExtraType, TileEntityMobSpawner.getMobID,
LanguageRegistry.addStringLocalization(Properties), and real shim classes for ILiquid, LiquidEvent, ServerList (reads/writes servers.dat) and
ClientBrandRetriever. Still open: Texture/TextureAtlasSprite (1.5.2 sheet textures), GuiConnecting, NEI GuiContainerManager/API.addKeyBind, ItemData, SoundPool.addSound,
TextureFXManager.getTextureDimensions, IClassTransformer.transform, map rendering, capes.