gottschcore-1.20.1-2.9.0.jar
Curse Maven Snippet
What's new
Changelog for GottschCore 1.20.1
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[2.9.0] - 2026-10-08
Fixed
SpawnUtil.spawnMobno longer discards every mob it creates. It treated anullreturn fromForgeEventFactory.onFinalizeSpawnas a cancelled spawn, but Forge returns the spawn data that was passed in (herenull) for an ordinary, uncancelled spawn, so every attempt was discarded and proximity spawners in every mod using this class fired and spawned nothing. The return value is now ignored, as Forge's own javadoc says it should be.WaterloggedFacingHalfBlocknow keepsWATERLOGGEDon placement.getStateForPlacementdiscarded the result ofsetValue, so a block placed into water pushed the water out instead of waterlogging (since 2.4.0).SpawnUtil.spawnMobnow rejects a candidate position that failsMob.checkSpawnObstruction(the full-bounding-box collision test), matching the check vanilla's ownBaseSpawnerperforms.NaturalSpawner.isSpawnPositionOkonly tests the targetBlockPos(and the block above it) for a full/suffocating block; it says nothing about whether the mob's actual hitbox clips solid geometry once positioned, e.g. a corner, pilaster or partial-shape block adjacent to the target cell. Without this check,spawnMobcould hand back a mob already embedded in a wall, which then took suffocation damage and died — intermittently, since it only bit when the random offset happened to land against geometry the single-block check let through.SpawnUtil.spawnAndAddMobnow adds the created/positioned mob to the world. It previously added an un-positioned, passed-in instance and discarded the actual spawned mob, so mob-set proximity spawners spawned nothing.ProximityMobSetSpawnerBlockEntity.executeno longer creates and finalizes a mob twice; it delegates spawning toSpawnUtil.spawnAndAddMob.MobSetDataHandlernow clears the registry at the start of each reload so removed/edited data packs no longer leave stale entries behind.MobSetDataHandlermerge/replace now reads thereplaceflag from the incoming data instead of the existing entry.
Changed
SpawnUtilreworked so creation and world-insertion are separate steps:spawnMob(...)creates, positions and finalizes a mob but does not add it to the world (an interception point for external mods to modify the entity first);spawnAndAddMob(...)performs the add. Removed the ignoredEntity mobparameters from both methods.MobSetDataRegistrybacking map is now aConcurrentHashMap(data pack reloads run off-thread);get(null)returns empty.MobCountconstructor normalizes counts to be non-negative withmin <= max.WeightedMobreduced to a plain record (removed redundant hand-written accessors andequals/hashCode/toString).
Added
StrictCodecs(mod.gottsch.forge.gottschcore.json) and its use throughoutworld.gen.structure.templatesystem: an optional field may now be omitted, but not wrong.- DFU's
optionalFieldOf(name, default)cannot tell "absent" from "present and malformed" —OptionalFieldCodecmaps any decode failure to an empty optional, so the default is substituted either way. Every field in the package was written that way, and the result was silent: a badprobabilitybecame0.0and the rule went inert; ONE bad entry in ablockspalette emptied the whole palette (a list codec fails as a unit) and the rule then reported itself inactive; a badfloor_growthobject becameNONE, losing the behaviour entirely. No error, no log line, pack loads, dungeon is merely plainer than authored. - All 19 optional fields across
AgingProcessor,AgingStage,BlockMatch,DecorationProcessor,DecorationRuleandWallGrowthRulenow fail the file on a malformed value, with the field name prepended to the message. Omitting a field still yields its default, so packs that simply do not set a key are unaffected. - Deliberately narrower than a closed schema: an undeclared key is still ignored, since a shared library's consumers may legitimately carry spare fields. Closing the schema stays a decision for the consuming mod's own records.
- DFU's
- A decoration palette entry may name an ENTITY instead of a block (
WeightedGrowth, formerlyWeightedBlock).{ "entity": "dungeons2:shrieker", "weight": 1 }grows a mob where a mushroom would go. Some things that read as scenery are mobs — GMM's Shrieker and Violet Fungus root themselves and never move — and this lets a datapack treat them as what they look like.- An entry names exactly one of
block/entity; both or neither is a load error rather than a guess. - Spawning happens in
finalizeProcessing, which receives a realServerLevelAccessor, and is clipped toStructurePlaceSettings#getBoundingBox— the chunk box during a piece placement, and the same exactly-once guard vanilla's ownStructureTemplate.placeEntitiesapplies.processBlockInfosis NOT chunk-clipped and a piece is placed once per chunk it spans, so without that clip a mob would be spawned once per overlapping chunk. The box is null unless someone set it, which is the honest signal for a single-shot caller; there, everything spawns. - Only
floor_growth/hanging_growth/floating_growthcan place an entity. The oriented rules (cobwebs,corner_cobwebs,wall_growth,underwater_growth) derive a block state from geometry — a facing, a half — which an entity has no equivalent of, so an entity in one of those palettes is refused with a warning rather than guessed at.
- An entry names exactly one of
- Weighted decoration palettes (
WeightedGrowth).DecorationRuleandWallGrowthRuleblockslists now accept either a bare block id or{"block": <id>, "weight": <int>}, mixed freely in one list. A bare id means weight 1, so every palette written before this keeps working unchanged and nothing needs migrating; encoding round-trips weight 1 back to a bare id so re-serialising a pack does not rewrite it into the verbose form.- An unweighted palette draws exactly as it did before. The pick is one
nextInt(totalWeight)walked over the cumulative weights; with all weights 1,totalWeight == sizeand the walk lands on the index the roll named — the same block, from the same single draw, as the previousblocks.get(nextInt(size)). That is deliberate and pinned byWeightedGrowthTest: these palettes are drawn during worldgen from a position-seeded random, so a draw consuming a different amount of randomness would silently re-decorate every world that already exists. weightis required in the object form, and 0 is legal (an entry parked without deleting it). A palette whose weights are all 0 reports its rule inactive rather than drawing nothing-shaped. Negative weights fail the decode. Required rather than defaulted because DFU'soptionalFieldOf(name, default)cannot tell "absent" from "present and invalid" — with a default of 1,"weight": -3decoded silently as 1.- Rules built in code use
DecorationRule.of(probability, List<Block>)/WallGrowthRule.of(...), which wrap at weight 1.
- An unweighted palette draws exactly as it did before. The pick is one
- Multi-set support wired end-to-end:
StructureMobSetBlockEntitynow loads/saves itsmobSetslist, andProximityMobSetSpawnerBlockEntityselects a set at trigger time frommobSetNameswhen no singlemobSetNameis set. - Documentation on
MobSetDataHandlerdescribing themob_setsdata pack folder and the requiredAddReloadListenerEventregistration by consuming mods. - New
world.gen.structure.templatesystempackage for shared processors built on vanilla's template system (worldgen/processor_listJSON), as opposed to the legacyGottschTemplatepath in the parent package.AgingProcessor— ages blocks along multi-stage decay chains and, unlike vanilla'sminecraft:rule, carries the source block's state properties onto the replacement. A vanillaProcessorRuleemits a fixedoutput_stateand drops properties, so ageing a stair/slab/wall with it silently resets facing/half/shape; this copies every property the source and replacement share, letting one rule age a whole family of shaped blocks. Chains are graduated: a stage is only reachable if the stage before it was rolled, capped byagings.AgingRule/AgingStage— the datapack model (block/output_blocks/probability).- An unknown block id now logs a warning (
BlockIds, used by every processor in the package).BuiltInRegistries.BLOCK.byNameCodec()looks strict but never fails: the block registry is a defaulted registry, so an unknown id silently decodes tominecraft:air, and a rule namingmosy_bricksquietly did nothing. It warns rather than failing the load because GottschCore is shared: a pack may legitimately name blocks from a mod the player hasn't installed, and should lose one rule, not stop loading. A consuming mod that wants strictness for its own content should check its shipped files in a test. - Randomness is derived from the block's absolute world position (
Mth.getSeed(pos), as vanilla'sRuleProcessordoes) rather than fromStructurePlaceSettings, so results are identical regardless of caller — required by callers that run a processor list over procedurally-built blocks, where a piece is processed once per chunk it overlaps and a block on a chunk seam must resolve the same way in both passes. - Registration is the consuming mod's job. GottschCore registers no
StructureProcessorType(most dependants never touch structure processors), so the class takes aSupplier<StructureProcessorType<?>>and exposesAgingProcessor.codec(supplier)instead of a staticCODEC. The registration idiom is documented on the class. - Note: alternative chains for the same source block are tried in order and the first that decays wins, so a later chain's authored probability is conditional on the earlier ones missing — two alternatives that should each fire 30% of the time are authored
0.3and0.43. DecorationProcessor— decoration that depends on a block's neighbours rather than on the block alone, which neitherminecraft:rulenorAgingProcessorcan express since both decide one block at a time. Behaviours (all off until a datapack gives them a probability and a palette):cobwebs,corner_cobwebs(an angled web gathered into the junction of a wall with a floor or ceiling, which needs two perpendicular surfaces and orients itself to them, including in rotated and mirrored pieces),wall_growth(clustering multiface growth on full-cube faces),floor_growth/hanging_growth(above and below adirtmatch),underwater_growth/floating_growth, andunsupported(deletes blocks left hanging once nothing holds them up). Checks are independent, not a cascade, and only cells the piece itself places as air are ever overwritten. Samecodec(supplier)registration idiom asAgingProcessor.BlockMatch/DecorationRule/WallGrowthRule— the datapack model for it.LevelIndependentProcessor— marker for a processor that never touches the level it is handed, deciding purely from the block list, the states in it, and their positions. That property is what lets a caller run a processor over a procedurally-built piece's whole block list instead of only the slice inside the chunk being generated: reading outside the activeWorldGenRegionis illegal, so a processor that reads must be clipped and one that doesn't, needn't be. Neighbour-aware processors must be unclipped (a neighbour map built from one chunk's slice is missing everything across the seam); per-block ones benefit, because being unclipped keeps them in the same pass and therefore in authored order.AgingProcessorandDecorationProcessorboth implement it. Callers that build blocks procedurally are expected to split their processor list into two passes on this marker; vanilla's own placement path never needs it.
- Test source set (JUnit 5,
useJUnitPlatform()), GottschCore's first, withAgingProcessorTestcovering property carry-over for stairs/walls/slabs, waterlogging survival, chain-stops-on-miss, theagingscap, alternative-chain precedence, and positional determinism,DecorationProcessorTestcovering each decoration behaviour, their independence, seam determinism, and the facing/rotation round trip,WeightedGrowthTestfor weighted and entity palettes,StrictFieldsTestfor malformed optional fields, andBlockIdsTestfor the unknown-block warning.
Deprecated
world.gen.structure.StructureProcessor(the legacyGottschTemplateplacement path). New processors should extend vanilla'snet.minecraft...templatesystem.StructureProcessorand register aStructureProcessorType, so they are datapack-authored viaworldgen/processor_listand apply to jigsaw/template placement for free.- Not scheduled for removal —
GottschTemplateis still in use and this is a direction marker for new code, not a removal notice. Consuming mods that extend it will now see deprecation warnings. - The legacy type and vanilla's share a simple name but are unrelated and not interchangeable; that is why the new processors live in a
templatesystemsub-package, where they cannot shadow vanilla's class on import.
- Not scheduled for removal —
[2.8.0] - 2026-05-25
Added
- New
commandpackage with shared formatting tools for admin and debug commands.CommandResponseFormatter— builds coloured status messages (success, failure, warning, info) in shorthand or full form. Works with either plainComponentobjects or translation keys. IncludesformatConfirmPrompt()for two-step destructive command flows.ReportBuilder— fluent builder for structured reports (e.g.inspectcommands). Auto-aligns label column, supports sections, blank lines, and notes.FormatterConstants— shared box-drawing characters, semantic icons, style helpers, clickable/suggestable component builders, andbuildConfirmButton()for confirmation prompts.
DimensionCoords— immutable coordinate class that extendsCoordswith aResourceKey<Level>dimension field. Supportssave()/load()NBT serialization (adds a"dimension"string tag alongside x/y/z). Defaults to the overworld when loading old data without a dimension tag. Factory methods:DimensionCoords.of(dimension, x, y, z),of(dimension, BlockPos),of(dimension, ICoords).
[2.6.0] - 2026-03-26
Changed
- Update BST - dimensional aware.
- ProximitySpawnerBlockEntity.
- Box added new methods.
- SpawnUtil.
Added
- MobCount, MobSetData, MobSetDataHandler, MobSetDataRegistry, WeightedMob
- StructureMobSetBlock, ProximityMobSetSpawnerBlockEntity, StructureMobSetBlockEntity
- MobSetConfiguration
[2.5.1] - 2025-09-23
Changed
- Fixed AbstractProximinityBlockEntity load() method to properly check for "proximity" value.
- this had prevented proximity from loading properly and always defaulting to the 5D value.
[2.5.0] - 2025-06-15
Added
- Interval implementation for bst package.
[2.4.0] - 2025-05-09
Added
- IHalfBlock block interface
- HalfBlock block
- FacingHalfBlock
- WaterloggedFacingHalfBlock block
- ModUtil class - contains asLocation(), mcLocation() methods, spawnMob(), spawnAndAddMob() methods.
[2.3.0] - 2024-10-27
Changed
- deprecated usage of Coords constructors in favor of static of() methods.
[2.2.0] - 2024-08-20
Changed
- changed WeightedCollection.add() to synchronized.
Added
- WeightedCollection.remove(T key) method.
This mod has no additional files