Changelog

Releases

Every Kore release with its full notes, pulled from GitHub at build time.

Changelogs cover what changed between two Minecraft versions, so a release with nothing new in-between has a short or empty entry.

221Releases
2.28.0Latest version
5Minecraft versions
2023Releasing since
41 of 221 releasesUnstable channels are hidden by default

Minecraft 26.31

26 Oct 2026today

Welcome to Kore 26.3!

kore-2.28.0-26.3-banner

Kore now targets Minecraft 26.3 Wilderness Bound, with its worldgen, loot data and compute changes. And what a cycle that was :') Ten snapshots, three pre-releases and three release candidates, sixteen Kore releases in total, and every new file type got its builder along the way.

The part I'm the proudest of is what Kore built on top of that. Provider maths is plain Kotlin now (rolls = 2 + score("kills", EntityTarget.THIS)), compute works from the data DSL and from scoreboard entities, and the helpers maths runs on it 3 to 24 times faster. helpers also gets NPCs with per-player conversations, particles share one model everywhere, and almost every provider field takes a plain number or a Kotlin range. Packs come out shorter too, and identical on the JVM and JS.

Heads up though, this cycle breaks a lot, probably the most since multiplatform. Most of it is mechanical renames to match the game, and the migration notes list every change from 2.16.0-26.2 with its before and after.

What's new?

The big stuff this cycle:

  • Provider expressions and compute: +, -, *, /, %, toFloat() and coerceIn build context provider trees and keep them small, and the same expressions feed compute from the data DSL, setTo { } on scoreboard entities and blockIdProvider().
  • Faster helpers maths: sin, cos, sqrt, distanceSquared, parabola and every ScoreVector helper run on compute, 3 to 24 times faster in game, and Entity.distanceTo gives the distance between two entities in three commands.
  • NPCs and conversations: clickable interactions, NPCs pairing a mannequin with a hitbox, and per-player conversations with timed lines, pauses and choices.
  • One particle model: a single ParticleOptions serves /particle, enchantment effects, environment attributes and the VFX shapes, covering every particle with options and fixing the ones Kore wrote wrong.
  • Plain numbers and ranges: rolls(1..3), maxUses(12), count(10) or blobFoliagePlacer(radius = 2, height = 3), no more constant(...) and uniform(...) everywhere.
  • Smaller, identical packs: SNBT string values the game reads back unquoted lose their quotes, inline resources in commands are written exactly like their file, and floats print the same on the JVM and JS.
  • Hoisting passes: two opt-in passes move inline context providers and predicates repeated across functions into their own files.
  • Interactive docs: a provider explorer sampling any provider with the game's formulas, a world height diagram, a mannequin builder with a 3D skin preview, a display transformation editor, a noise explorer and conversation mockups. Every doc page also has a Markdown copy for LLMs, and the install snippets always show the latest release.

Code examples

Provider expressions and compute

pool {
	rolls = 2 + score("kills", EntityTarget.THIS)
}

function("maths") {
	compute(self()) { (score("kills", EntityTarget.TARGET_ENTITY) + 3 + 4) % 7 }

	data(storage("foo")) {
		compute("baz", self()) { score("kills", EntityTarget.TARGET_ENTITY) + 1 }
		modify("list") { append(compute(2.5f)) }
	}
}
Kotlin
compute entity @s integer {type:"minecraft:mod",left:{type:"minecraft:add",inputs:[<kills>,7]},right:7}
data modify storage minecraft:foo list append compute default float {type:"minecraft:constant",value:2.5f}
Mcfunction

Score expressions

One compute command per expression, where scoreboard players operation needs a temporary holder per step.

function("combo") {
	val kills = player.getScoreEntity("kills")
	val bonus = fakePlayer("bonus").getScoreEntity("game")
	val points = fakePlayer("points").getScoreEntity("game")

	points setTo { score(kills) + score(bonus) * 2 }

	val chance = fakePlayer("chance").getScoreEntity("game")
	chance.setTo(1000f) { uniform(0.5f, 2f) }  // a score between 500 and 1999

	entity(EntityTypes.ZOMBIE).distanceTo(entity(EntityTypes.VILLAGER), fakePlayer("distance").getScoreEntity("game"))
}
Kotlin

Plain numbers and ranges

lootTable("treasure") {
	pool(1..3) {
		bonusRolls(0f..1f)
		entries {
			item(Items.DIAMOND_SWORD) {
				modifier {
					setCount(1..5)
					enchantWithLevels(levels = 20..39)
				}
			}
		}
	}
}

villagerTrade("wheat_for_emeralds") {
	wants(Items.WHEAT, 16..24)
	gives(Items.EMERALD)
	maxUses(8..12)
	xp(2)
}

placedFeature("my_ore", Features.ORE_IRON) {
	inSquare()
	count(10)
	heightRange(absolute(32))
}
Kotlin

NPCs and conversations

val questGiver = npc("quest_giver") {
	val quest = objective("quest")

	mannequin {
		customName("Elder Mira", Color.GOLD)
		playerProfile("Ayfri")
	}

	val intro = conversation("quest_intro") {
		speaker = textComponent("Elder Mira", Color.GOLD)
		choiceStyle = ChoiceStyle.CHAT

		line("Traveler, the mines have gone quiet.")
		wait(2.seconds)
		choice("Will you take this pickaxe and look?") {
			option("Accept", Color.GREEN, hover = "Take the pickaxe") {
				step {
					give(self(), Items.IRON_PICKAXE)
					scoreboard.players.set(self(), quest, 1)
				}
				line("Good luck, and come back alive.")
			}
			option("Decline", Color.RED) { line("I understand. The offer stays open.") }
		}
	}

	onRightClick { intro.advance() }
}
Kotlin

Progress is stored per player, so ten players can talk to the same NPC at once, and a player with nothing pending costs no command per tick.

Particles

function("dust_ring") {
	val orange = dustParticle(rgb(0xFF8800), 1.5f)

	for ((x, z) in listOf(102 to 100, 100 to 102, 98 to 100, 100 to 98)) {
		particle(orange, vec3(x, 64, z), count = 3, mode = ParticleMode.FORCE)
	}
}

drawShape("arena_intro") {
	shape = Shape.SPIRAL
	particle = dustParticle(rgb(0x55FF55), 1.5f)
	radius = 4.0
	points = 60
	height = 6.0
	turns = 5
}
Kotlin
particle minecraft:dust{color:16746496,scale:1.5f} 102 64 100 0 0 0 0 3 force
Mcfunction

Block IDs

blockIdProvider() turns the block read by compute block into a number, so one command stores "which block is this" in a score instead of one execute if block per candidate.

val ids = blockIdProvider()
val below = vec3(0.relativePos, (-1).relativePos, 0.relativePos)

function("check_ground") {
	execute {
		storeResult { score(self(), "ground") }
		run { compute(below, ids) }
	}
	execute {
		ifCondition { score(self(), "ground", rangeOrInt(blockId(Blocks.SLIME_BLOCK))) }
		run { say("Bounce!") }
	}
}
Kotlin

Performance

helpers maths measured in game, ms per tick for 100,000 calls:

  • sin: 1745 → 235 ms, cos: 1098 → 123 ms
  • sqrt: 1254 → 200 ms, still exact on every Int
  • distanceSquared: 1248 → 387 ms, parabola: 594 → 167 ms
  • ScoreVector.dot: 702 → 173 ms, lengthSquared: 822 → 278 ms, cross: 1356 → 405 ms
  • ScoreVector.length: 3778 → 159 ms, distanceTo: 3445 → 163 ms, normalize: 4611 → 659 ms
  • Entity.distanceTo against two ScoreVector.setToPosition plus distanceTo, on markers: 7320 → 1156 ms

Migration notes

What to change coming from 2.16.0-26.2, grouped by area.

Loot tables, predicates and item modifiers

Context providers

Number providers are split into int and float providers. An int field (rolls, counts, levels, maxUses, xp, entityScores ranges...) takes an int provider, constant(3) or uniform(1, 5), and a float field (bonusRolls, setDamage, randomChance...) a float provider, constant(3f) or uniform(1f, 5f). fromInt(...) and fromFloat(...) convert between them. The builders only resolve inside the blocks that take a provider (loot tables, pools, item modifiers, predicates, villager trades, trade sets): a provider built outside one uses its class or moves into the block.

Before After
sum(...) add(...)
scoreNumber score (int only)
storageNumber intStorage, floatStorage
environmentAttribute intEnvironmentAttribute, floatEnvironmentAttribute
binomial(5f, 0.5f) binomial(5, 0.5f)
valueCheck intValueCheck, floatValueCheck
intRange(0f, 10f) intRange(0, 10)
limitCount(64) limitCount(max = constant(64))

The classes follow the builders: ConstantNumberProvider is ConstantContextIntProvider or ConstantContextFloatProvider, and the same goes for UniformNumberProvider, ScoreNumberProvider (int only), StorageNumberProvider, EnvironmentAttributeNumberProvider and EnchantmentLevelNumberProvider (float only). BinomialNumberProvider is BinomialContextIntProvider, SumNumberProvider is AddContextIntProvider or AddContextFloatProvider, and IntOrNumberProvidersRange is ContextIntProviderBounds.

// Before
val rolls = uniform(2f, 5f)
lootTable("my_table") {
	pool {
		this.rolls = rolls
		bonusRolls = sum(scoreNumber("luck", EntityTarget.THIS), constant(1f))
	}
}

// After
lootTable("my_table") {
	pool(2..5) {
		bonusRolls = add(fromInt(score("luck", EntityTarget.THIS)), constant(1f))
	}
}
Kotlin

Predicate files hold one condition, named by type

The discriminator of a condition is type, and a predicate file holds one condition: several conditions declared in a predicate { } block become the terms of one all_of.

predicate("two_conditions") {
	randomChance(0.5f)
	weatherCheck(raining = true)
}
Kotlin
// Before
[
	{ "condition": "minecraft:random_chance", "chance": 0.5 },
	{ "condition": "minecraft:weather_check", "raining": true }
]

// After
{
	"type": "minecraft:all_of",
	"terms": [
		{ "type": "minecraft:random_chance", "chance": 0.5 },
		{ "type": "minecraft:weather_check", "raining": true }
	]
}
JSON

Every predicate field holds one condition

Loot tables, pools and entries, item functions, advancement triggers, dialogs and enchantment requirements take one condition, several conditions being wrapped in an all_of the same way. conditions { } is condition { }, and the loot table, pool and entry functions { } is modifier { }.

// Before
lootTable("t") {
	functions { setCount(2f) }
	pool {
		conditions { killedByPlayer() }
		functions { enchantRandomly() }
	}
}
setCount(1f) { conditions { randomChance(0.5f) } }
tick("check") { conditions { weatherCheck(raining = true) } }
LootPool(constant(1f))

// After
lootTable("t") {
	modifier { setCount(2) }
	pool {
		condition { killedByPlayer() }
		modifier { enchantRandomly() }
	}
}
setCount(1) { condition { randomChance(0.5f) } }
tick("check") { condition { weatherCheck(raining = true) } }
LootPool(rolls = ConstantContextIntProvider(1))
Kotlin

PredicateAsList is removed: AllOf and AnyOf take an inlinable list of conditions as terms, and EntityOrPredicates and LocationOrPredicates hold one condition, without legacyEntity and legacyLocation. The allOf { }, anyOf { }, entity { } and location { } builders are unchanged.

Item functions use type

An item function names its kind in type instead of function. A modifier holding one function is written as that object, several ones as a list, and ItemModifierAsList is InlinableItemModifier. An itemModifier(name) { } without any function, or a slotSource(name) { } without any source, throws when generated.

// Before
[{ "function": "minecraft:set_count", "count": 2.0, "conditions": [{ "condition": "minecraft:killed_by_player" }] }]

// After
{ "type": "minecraft:set_count", "count": 2, "condition": { "type": "minecraft:killed_by_player" } }
JSON

reference is a bare ID

The reference predicate, item modifier and slot source classes are removed: the builders write the bare ID string. The item modifier reference(name: String) is gone, it takes an ItemModifierArgument or ItemModifierTagArgument.

// Before
reference(PredicateArgument("is_night", "my_pack"))  // { "condition": "minecraft:reference", "name": "my_pack:is_night" }
reference("my_pack:base")                            // { "function": "minecraft:reference", "name": "my_pack:base" }

// After
reference(PredicateArgument("is_night", "my_pack"))  // "my_pack:is_night"
reference(ItemModifierArgument("base", "my_pack"))   // "my_pack:base"
Kotlin

Loot table and tag entries

The tag entry writes items instead of name, and expand is optional and named. The loot_table entry value is a list, written bare when it holds one element.

// Before
tag(Tags.Item.ARROWS, true)  // "name": "#minecraft:arrows", "expand": true

// After
tag(Tags.Item.ARROWS, expand = true)  // "items": "#minecraft:arrows", "expand": true
lootTable(LootTables.Equipment.TRIAL_CHAMBER, LootTables.Equipment.TRIAL_CHAMBER_MELEE, expand = true)
Kotlin

Loot table types

LootTableType is a deprecated alias of the generated ContextKeySets, so the old code still compiles with a warning. The type is written as an ID ("type": "minecraft:chest"), and the archaeology context is ARCHAEOLOGY, written archaeology like the game.

// Before
lootTable("brush") { type = LootTableType.ARCHEOLOGY }

// After
lootTable("brush") { type = ContextKeySets.ARCHAEOLOGY }
Kotlin

blockStateProperty is matchBlock

// Before
blockStateProperty(Blocks.COMPOSTER) { this["level"] = "0" }  // "block", "properties"

// After
matchBlock(Blocks.COMPOSTER) { state("level", "0") }          // "blocks", "state"
Kotlin

Damage tags

tag(...) takes any number of damage types or tags, so expected is named.

// Before
tag(Tags.DamageType.IS_FIRE, false)

// After
tag(Tags.DamageType.IS_FIRE, expected = false)
Kotlin

Item function fields

The colors of setCustomModelData are CustomModelDataColor entries (a fixed color or a provider). setStewEffect takes Effects.*. explorationMap requires its destination, one or several structures or tags. modifyContents takes modifier { }, and setLootTable has no block entity type and takes a loot table ID.

// Before
setStewEffect { potionEffect(Potions.NIGHT_VISION, constant(200f)) }
explorationMap { destination = Tags.Worldgen.Structure.ON_TREASURE_MAPS }
modifyContents(ContentComponentTypes.CONTAINER) { modifiers { enchantRandomly() } }
setLootTable(BlockEntityTypes.CHEST, "minecraft:chests/simple_dungeon", seed = 1)

// After
setStewEffect { potionEffect(Effects.NIGHT_VISION, 200) }
explorationMap(Tags.Worldgen.Structure.ON_TREASURE_MAPS)
modifyContents(ContentComponentTypes.CONTAINER) { modifier { enchantRandomly() } }
setLootTable(LootTables.Chests.SIMPLE_DUNGEON, seed = 1)
Kotlin

potion_contents item predicate

The predicate is an object with potions and effects, so its block configures that object.

// Before
potionContents { add(Potions.SWIFTNESS) }

// After
potionContents { potions(Potions.SWIFTNESS) }
potionContents(Potions.SWIFTNESS) // unchanged
Kotlin

Advancements, villager trades, recipes and slots

Triggers

conditions { } of a trigger is condition { }, and entity and location fields also take the ID of a predicate file. channeledLightning victims are a list of predicates. beeNestDestroyed, enterBlock and slideDownBlock match a blocks list and a state instead of one block, brewedPotion matches a potion_contents predicate, the recipe triggers take recipes, and playerGeneratesContainerLoot takes lootTables.

// Before
channeledLightning("lightning_rod") {
	victim { conditions { entityProperties { entityType(EntityTypes.CREEPER) } } }
}
beeNestDestroyed("nest") { block = Blocks.BEE_NEST }
brewedPotion("swift") { potion = Potions.SWIFTNESS }

// After
channeledLightning("lightning_rod") {
	victim { conditionEntity { entityType(EntityTypes.CREEPER) } }
	victim(PredicateArgument("is_villager", "my_pack"))
}
beeNestDestroyed("nest") { blocks(Blocks.BEE_NEST, Blocks.BEEHIVE) }
brewedPotion("swift") { potion(Potions.SWIFTNESS) }
recipeCrafted("craft_pickaxe", Recipes.DIAMOND_PICKAXE, Recipes.IRON_PICKAXE)
Kotlin

Advancement backgrounds

Generating a root advancement (no parent) with a display but no background throws, and so does a child advancement with a background.

Villager trades

givenItemModifiers is givenItemModifier, which also takes an item modifier ID. wants and additionalWants are TradeCosts instead of ItemStacks, the wants(...) builders are unchanged.

// Before
givenItemModifiers { enchantRandomly() }

// After
givenItemModifier { enchantRandomly() }
givenItemModifier { reference(ItemModifierArgument("enchant_boots", "my_pack")) }
Kotlin

Recipes

cookingTime is a required parameter of smelting, blasting, smoking and campfireCooking. RecipeTypes.CRAFTING_SPECIAL("book cloning") keeps working, but the CraftingSpecial object, CraftingSpecialEntry and RecipeTypes.values are removed. CraftingTransmute.result and CraftingSpecialMapExtending.result are TransmuteResults, their result(...) builders are unchanged.

// Before
smelting("iron_ingot") { cookingTime = 200 }

// After
smelting("iron_ingot", cookingTime = 200) { }
Kotlin

Slot sources and slot ranges

Slot sources moved from features.loottables.entries.slotsource to features.slotsources. Every slot range is a slot written <name>.*, so ARMOR writes armor.*, and ARMOR[index] is gone since only numbered ranges like HOTBAR have indexed slots. InventoryManager.clear(slot) writes item fill ... with minecraft:air to empty every selected slot.

Worldgen

Configured features are Features

Configured features are written to worldgen/feature with their fields next to type. The builders don't change, but the generated ConfiguredFeatures and ConfiguredFeatureArgument are Features and FeatureArgument.

// Before
placedFeature("my_tree", ConfiguredFeatures.ACACIA)

// After
placedFeature("my_tree", Features.ACACIA)
Kotlin

Surface rules are material rules

The old names stay as deprecated aliases, and rules and conditions can live in their own files, used by ID.

// Before
noiseSettings("my_settings") {
	surfaceRules { block(Blocks.STONE) }
}

// After
noiseSettings("my_settings") {
	materialRules { block(Blocks.STONE) }
}
Kotlin

Configured carvers are carvers

The package features.worldgen.configuredcarver is features.worldgen.carver, and every name drops Configured. The generated Carvers used to list carver types: those are CarverTypes now, and Carvers lists the carvers themselves, so old code using Carvers keeps compiling with another meaning. Tags.Block.OVERWORLD_CARVER_REPLACEABLES and NETHER_CARVER_REPLACEABLES are gone.

Before After
configuredCarvers { } carvers { }
configuredCarver(...) carver(...)
configuredCarverTag(...) carverTag(...)
ConfiguredCarversScope CarversScope
ConfiguredCarvers (generated) Carvers
ConfiguredCarverArgument CarverArgument
Carvers (generated carver types) CarverTypes

lavaLevel, replaceable, debugSettings (with its airState, waterState, lavaState and barrierState) and netherCave are gone. The cave yScale is roomVerticalRadiusMultiplier, and the canyon one moves into shape.

// Before
configuredCarvers {
	cave("my_cave") {
		yScale = uniform(0.1f, 0.9f)
		lavaLevel = absolute(-54)
		replaceable(Blocks.STONE, Blocks.DIRT)
	}
	canyon("my_canyon") { yScale = constant(3.0f) }
}

// After
carvers {
	cave("my_cave") { roomVerticalRadiusMultiplier = uniform(0.1f, 0.9f) }
	canyon("my_canyon") { shape { yScale = constant(3.0f) } }
}
Kotlin

Basalt and glowstone features

// Before
configuredFeaturesBuilder.basaltColumns("columns", reach = 3, height = 6)
configuredFeaturesBuilder.basaltPillar("pillar")
configuredFeaturesBuilder.glowstoneBlob("blob")

// After
configuredFeaturesBuilder.steppedColumnCluster("columns") {
	block = simpleStateProvider(Blocks.BASALT)
	canReplace { matchingBlocks(Blocks.LAVA) }
	continueThrough { replaceable() }
	cannotPlaceOn(Blocks.LAVA)
	columnReach = constant(3)
	columnCount = uniform(1, 4)
	height = constant(6)
	clusterReach = constant(3)
}
configuredFeaturesBuilder.singleBlockPillar("pillar", VerticalDirection.DOWN) {
	block = simpleStateProvider(Blocks.BASALT)
}
configuredFeaturesBuilder.randomNeighborSpread("blob") {
	block = simpleStateProvider(Blocks.GLOWSTONE)
	acceptedNeighbors(Blocks.GLOWSTONE, Blocks.NETHERRACK)
	canReplace { matchingBlocks(Blocks.AIR) }
	attempts = constant(1500)
	xzOffset = uniform(-7, 7)
	yOffset = uniform(-11, 0)
}
Kotlin

Removed features

coralMushroom, desertWell, kelp, netherForestVegetation, randomPatch, seaPickle, seagrass, twistingVines and weepingVines are removed, and sculkPatch loses catalystChance and extraRareGrowths (place the catalyst and shriekers with simple_block features in a sequence). coralClaw and coralTree require their placed feature.

// Before
configuredFeaturesBuilder.coralTree("my_coral")

// After
configuredFeaturesBuilder.coralTree("my_coral", PlacedFeatureArgument("coral_overlay", "my_pack"))
Kotlin

Placement modifiers

randomOffset is offset, with one int provider per axis. count(), countOnEveryLayer(), rarityFilter() and heightRange() have no defaults anymore, since those placed nothing. environmentScan takes an Int maxSteps, and SearchDirection is VerticalDirection.

// Before
randomOffset(xzSpread = constant(1), ySpread = uniform(-2, 2))
environmentScan(SearchDirection.DOWN, maxSteps = constant(12)) { targetCondition { solid() } }
count()

// After
offset(constant(1), uniform(-2, 2), constant(1))
environmentScan(VerticalDirection.DOWN, 12) { targetCondition { solid() } }
count(10)
Kotlin

Feature fields typed like the game

  • hugeFungus: hatState, stemState, decorState and validBaseBlock are block states, blockState(Blocks.DIRT) instead of simpleStateProvider(Blocks.DIRT).
  • speleothemCluster: density and wetness are float providers, chanceOfSpeleothemAtMaxDistanceFromCenter a Float.
  • vegetationPatch and waterloggedVegetationPatch: xzRadius is an int provider.
  • randomSelector: default and each entry's chance are required.
  • template, fossil and the single / legacySingle pool elements hold a ProcessorListOrInline, and Sequence.features and SimpleRandomSelector.features a list of PlacedFeatureOrInline. The builders taking IDs are unchanged.
Before After
DeltaFeature.content contents
EnvironmentScan.directionOfSearchDirection directionOfSearch
MangroveRootPlacer.canGrowTrough canGrowThrough
UpwardsBranchingTrunkPlacer.canGrowthThrough canGrowThrough

Block states and block state providers

Block states write id and properties, or a bare block ID without properties: BlockState.name is id, like BlockStateBuilder.id and the block parameter of blockState(...), simpleStateProvider and rotatedBlockProvider. The provider classes carry their full name: SimpleStateProvider, RandomBlockProvider, RotatedBlockProvider, NoiseProvider, DualNoiseProvider, NoiseThresholdProvider, RandomizedIntStateProvider, RuleBasedStateProvider (and its Rule) and WeightedStateProvider (and its Entry) are SimpleBlockStateProvider, RandomBlockStateProvider, RotatedBlockStateProvider, NoiseBlockStateProvider, DualNoiseBlockStateProvider, NoiseThresholdBlockStateProvider, RandomizedIntBlockStateProvider, RuleBasedBlockStateProvider and WeightedBlockStateProvider, and the rotated provider's state is a block state provider. Only calls with named arguments or reading these properties change.

// Before
val block = state.name
blockState { name = Blocks.STONE }

// After
val block = state.id
blockState { id = Blocks.STONE }
Kotlin

Density functions

Fields follow the game: single-input nodes write input, two-input nodes left and right, constant writes a Double value, and the shift nodes write noise.

Before After
invert(...) reciprocal(...)
Add(argument1 = a, argument2 = b) Add(left = a, right = b)
yClampedGradient { fromY; toY } gradient { axis = Axis.Y; fromCoordinate; toCoordinate }
endIslands(...) endOuterIslands(...), without the central island
shiftedNoise(...) noise(...) { shiftX(...) }
interpolated(name, input) interpolated(name, input, cellSizeXz, cellSizeY)
cacheOnce(...) cache(...)
cache2D, cacheAllInCell, flatCache removed
// Before
yClampedGradient("depth_bias") {
	fromY = -64
	toY = 320
	fromValue = 1.0
	toValue = -1.0
}

// After
gradient("depth_bias") {
	axis = Axis.Y
	fromCoordinate = -64
	toCoordinate = 320
	fromValue = 1.0
	toValue = -1.0
}
Kotlin

Noises and noise settings

  • firstOctave and amplitudes are baseOctave and amplitudeModifiers, in noise files and in the noise-based block state providers, whose Noise class is NoiseParameters.
  • aquifersEnabled is aquifers { }, and oreVeinsEnabled is the oreVein(...) material rule. The NoiseRouter fields barrier, fluidLevelFloodedness, fluidLevelSpread, lava, veinToggle, veinRidged and veinGap are removed, and preliminarySurfaceLevel is chunkSurfaceLevel.
  • noiseOptions(minY, height, sizeHorizontal, sizeVertical) is noiseOptions(minY, height).
  • spawnTarget is built with spawnTargetPoint { }, each density function mapped to a value or a range.
// Before
dp.noise("hills") {
	firstOctave = -5
	amplitudes(1.0, 0.5, 0.25)
}
dp.noiseSettings("terrain") {
	aquifersEnabled = true
	oreVeinsEnabled = true
	noiseOptions(-64, 384, 1, 2)
	spawnTarget += multiNoiseBiomeSourceParameters(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
}

// After
dp.noise("hills") {
	baseOctave = -5
	amplitudeModifiers(1.0, 0.5, 0.25)
}
dp.noiseSettings("terrain") {
	aquifers { barrier(DensityFunctions.Overworld.BASE_3D_NOISE) }
	materialRules {
		oreVein(Blocks.COPPER_ORE, Blocks.RAW_COPPER_BLOCK, Blocks.GRANITE, DensityFunctions.Overworld.OreVein.COPPER_DENSITY)
	}
	noiseOptions(-64, 384)
	spawnTargetPoint {
		this[DensityFunctions.Overworld.CONTINENTS] = -0.11..1.0
		this[DensityFunctions.Overworld.DEPTH] = 0.5
	}
}
Kotlin

Biome spawns are environment attributes

spawners, spawnCosts and creatureSpawnProbability are removed from Biome, and Spawn has one count int provider. The spawner(type, weight, minCount, maxCount) builder is unchanged.

// Before
dp.biome("my_biome") {
	creatureSpawnProbability = 0.07f
	spawners { creature { spawner(EntityTypes.COW, weight = 6, minCount = 2, maxCount = 4) } }
}

// After
dp.biome("my_biome") {
	attributes {
		creatureWorldGenSpawnProbability(0.07f)
		naturalMobSpawns {
			spawnsByCategory { creature { spawner(EntityTypes.COW, weight = 6, minCount = 2, maxCount = 4) } }
		}
	}
}
Kotlin

Environment attribute builders

ambientParticles takes particle(options, probability) entries in its block, written under particle. ambientSounds and backgroundMusic are configured in their block only. In bedRule, explodes is destroyOnUse, next to the new destroyOnLeave, so a positional third argument now sets destroyOnLeave, and the overloads taking an instance are removed.

// Before
ambientParticles(Particle(ParticleOptions(Particles.ASH), 0.01f))
ambientSounds(additions = listOf(AdditionalSound(SoundEvents.Ambient.CAVE, 0.01f)))
bedRule(BedSleepRule.NEVER, BedSleepRule.NEVER, explodes = true)

// After
ambientParticles { particle(simpleParticle(Particles.ASH), 0.01f) }
ambientSounds { addition(SoundEvents.Ambient.CAVE, 0.01f) }
bedRule(BedSleepRule.NEVER, BedSleepRule.NEVER, destroyOnUse = true)
Kotlin

Particles, components and entities

Particles

particles { } and its builders (dragonBreath, flash, fallingDust...) are gone, as are ParticleData, the enchantment particleType(...), dustParticleType(...) and the other *ParticleType builders and classes: pass a ParticleOptions from the factories in io.github.ayfri.kore.data.particle. particle(Particles.X, ...) still works for particles without options. The VFX particle field takes a ParticleOptions. ColorAsDoubleArraySerializer, RGB.fromDoubleArray and the normalizedArray getters are removed, since particles write packed ints.

// Before
particles { dust(Color.RED, 1.0, vec3()) }
spawnParticles(Particles.ANGRY_VILLAGER, ParticlePositionType.ENTITY_POSITION, ParticlePositionType.ENTITY_POSITION)
drawCircle("fire_ring", Particles.FLAME, radius = 5.0, points = 16)

// After
particle(dustParticle(Color.RED), vec3())
spawnParticles(simpleParticle(Particles.ANGRY_VILLAGER), ParticlePositionType.ENTITY_POSITION, ParticlePositionType.ENTITY_POSITION)
drawCircle("fire_ring", simpleParticle(Particles.FLAME), radius = 5.0, points = 16)
Kotlin

Components

  • swingAnimation and SwingAnimationComponent are attackAnimation / AttackAnimationComponent and interactAnimation / InteractAnimationComponent, and SwingAnimationType moves to io.github.ayfri.kore.arguments.enums.
  • mapColor(...) and MapColorComponent are removed.
  • Trim materials take a palette from Textures.Palettes.Trim (was Textures.Trims.ColorPalettes), and overrideArmorAsset(s), overrideArmorMaterial(s) and the ArmorMaterial enum are gone.
  • Entity variant components are written under their real IDs, axolotl/variant instead of axolotl_variant. The output changes, the builders don't.
  • The texture, cape and elytra of a profile take a PlayerSkinTextureArgument, CapeTextureArgument and ElytraTextureArgument. textureProfile("namespace:path") still takes a string.
// Before
import io.github.ayfri.kore.arguments.components.item.SwingAnimationType
swingAnimation(SwingAnimationType.STAB, duration = 10)
trimMaterial("ruby", Textures.Trims.ColorPalettes.AMETHYST) { description("Ruby", Color.RED) }

// After
import io.github.ayfri.kore.arguments.enums.SwingAnimationType
attackAnimation(SwingAnimationType.STAB, duration = 10)
trimMaterial("ruby", Textures.Palettes.Trim.AMETHYST) { description("Ruby", Color.RED) }
Kotlin

Entity summon data and display entities

  • ItemEntitySummonData.displayName, displayNameVisible and displayName(text) are the shared customName, customNameVisible and customName(text, color), and customName is a ChatComponents.
  • motion is a List<Double> and rotation a List<Float>, the motion(dx, dy, dz) and rotation(yaw, pitch) builders are unchanged. pos is removed, since summon takes the position, and air is a Short.
  • itemEntitySummonData { } is removed, configure the entity in itemStack(...).summon { }.
  • Display entities: width, height and viewRange are Floats, and TextDisplay.text is a ChatComponents.
// Before
itemStack(Items.DIAMOND).summon { displayName("Shop") }
width = 2
text = text("Hello", Color.GOLD)

// After
itemStack(Items.DIAMOND).summon { customName("Shop") }
width = 2f
text = textComponent("Hello", Color.GOLD)
Kotlin

Helpers maths

  • distanceSquared, parabola and the ScoreVector dot, cross and lengthSquared store 0 when the result doesn't fit an Int, instead of wrapping.
  • They throw when building the pack if a score belongs to a selector that can match several entities: use limitToOne.
  • HelpersConstants.mathDisplayUuid is removed. A world that ran an older version keeps its text_display math entity until it is killed.

Generated code and SNBT

Root entries of generated trees are SCREAMING_CASE

Generated lists with folders (Recipes, TemplatePools, Noises, DensityFunctions, Structures, MaterialRules, SoundEvents, EnchantmentProviders) name their root entries like enum entries.

// Before
TemplatePools.Empty
Noises.Continentalness
DensityFunctions.ShiftX

// After
TemplatePools.EMPTY
Noises.CONTINENTALNESS
DensityFunctions.SHIFT_X
Kotlin

SNBT keys

encodeToSnbt writes the properties of any @Serializable class in snake_case, like the data pack JSON, and decodeFromSnbt reads them back, @JsonSerialName setting a different key. Inline resources in commands are written like their data pack file, so default values appear and string values lose the quotes the game doesn't need, which the game reads the same way.


Changelog

Documentation

  • docs(helpers): Open the mannequin page on summoning one with a player skin, fix the display transformation snippets and pivots, and show the real UUID handle selectors of mannequins and display entities. d800950 5d21d84
  • docs(itemmodifiers, references): Describe exploration_map as adding map data to the item it applies to, and note that lists mix IDs and inline values and that a tag can only replace the whole list. bfc940f d572c5b e098464
  • docs(loot-tables): Document that number providers compute 32-bit floats, so score providers and entity_scores ranges lose precision past 2^24 (MC-254370). fd09e41
  • docs(worldgen): Document every configured feature, tree placer and tree decorator with its in-game effect, vanilla uses, ranges and defaults, and explain how to tune carver, provider, feature, noise and biome parameters with vanilla reference values and links to misode's generators. 348f8de 2b616b4 0fdb14e e547598
  • docs(worldgen): Note that final_density no longer adds the beardifier and that density functions are evaluated in single precision. 0e91635 f2faf25
  • feat(website): Add the provider explorer, world height diagram, mannequin builder with a 3D skin preview, display transformation editor, noise explorer, chat and dialog choice mockups, conversation player and NPC hitbox visuals to the doc pages. 9a536e1 5105122 30e10b1 c2cba3b 6075657 cf0b7a6
  • feat(website): Serve a clean Markdown copy of every doc page, rebuild llms.txt and llms-full.txt from them, and fill the docs' install snippets from the latest releases at build time. 537c119 1a3575e
  • fix(website): Let inline code wrap anywhere, and tokenize SNBT compounds, selectors and bracketed components in mcfunction highlighting. 27fdb82 df38b74

New Features

  • feat(advancements): Take one inline predicate or predicate ID in trigger entity and location fields and a predicate list in channeled_lightning victims, match brewed_potion with a potion_contents predicate, accept recipe lists in the recipe triggers and loot table lists and tags in player_generates_container_loot and the loot reward, and replace the block of bee_nest_destroyed, enter_block and slide_down_block with a blocks list and state, with tests and docs. 7e6697a 5945201 f74f3c7 18db310 1024dbb
  • feat(advancements): Require a display background on root advancements and forbid it on children, with tests and docs. dfc420e
  • feat(blocktransformers, components): Add the block_transformer resource and the block_transformer item component referencing it, with rules taking any block state provider and update_from_neighbors, with tests and docs. 069c231 705efb9 6e97bd6
  • feat(commands): Accept an inline configured feature in /place feature, with tests and docs. 0f1ad17
  • feat(commands): Add the compute command and compute sources in the data DSL, with tests and docs. 80b26f9 91b74ff
  • feat(commands): Add the posteffect command and the generated PostEffects list, with tests and docs. c84051a
  • feat(commands): Add the animation and duration arguments to swing, none and a 0 duration included, with tests and docs. 186effe 7481782
  • feat(commands): Take slot sources in /item and /execute if items, add /item fill, /item override and /execute if slots, and make slot sources data-driven in features.slotsources with the container origin, with tests and docs. 868096a
  • feat(components, providers): Split number providers into the context_int_provider and context_float_provider families with their files, references, ranges, value checks and compute modes, add the conditional, number_dispatcher, weighted_list, avg, max, min and mul providers with add replacing sum, scope their builders to NumberProviderScope, and add the compostable item component, with tests and docs. c72dd5b edd58bf 664bd84 e82eaad a42dc3f 09c4cd7 5e3d65e db97975
  • feat(components): Accept texture, cape, elytra and model overrides on player profiles, typed with the generated PlayerSkinTextureArgument, ElytraTextureArgument and CapeTextureArgument, with tests and docs. a8eff1b b303a36
  • feat(components): Add directionalParticles to the teleport_randomly consume effect, with tests and docs. 5372e42
  • feat(components): Add the cooking_fuel, brewing_fuel, sign_text_front, sign_text_back, mob_visibility, villager_food, waxed and cushion/color components, the fuels taking plain numbers or provider IDs, with tests and docs. 5511726 dc9051c df6e5cd af32dbe
  • feat(components): Match potion effects in the potion_contents component predicate, its potions moving under potions, with tests and docs. 66c9380
  • feat(decorated-pots): Write pot_decorations as named item stacks and add the provides_pottery_pattern component and the data-driven decorated_pot_pattern, with tests and docs. 594d462
  • feat(environmentattributes): Add natural_mob_spawns with the overlay modifier, creature_world_gen_spawn_probability and the append modifier of ambient_particles, and write spawn entries with a single count provider, with tests and docs. f6e6257
  • feat(gametest): Add the test instance dimension, with tests and docs. 1a8a447
  • feat(generators): Add Generator.generateJsonElement, the generated content as a JsonElement, and build the Fabric load conditions on it, with tests and docs. 1091e41
  • feat(helpers): Add a generated block ID context int provider summing bit block tags, with tests and docs. a4f41cf
  • feat(helpers): Add equipment, custom name, rotation, tags and the other entity fields to mannequins, and accept any text component in text displays, with tests and docs. 6921c69 e116726
  • feat(helpers): Add interaction entities with right and left click callbacks, and NPCs pairing a mannequin with a clickable interaction, with tests and docs. f000042 51d27a2
  • feat(helpers): Add per-player conversations with timed lines, click pauses and dialog and chat choices, with tests and docs. 133ad0e
  • feat(helpers): Take ParticleOptions in the VFX shapes, for colored particles, with tests and docs. 450fd49
  • feat(instruments): Add the instrument durability_damage, with tests. 99c8f0b
  • feat(itemmodifiers, loottables): Accept plain numbers and ranges for pool rolls, score and storage fallbacks, enchant_with_levels levels, stew effect durations, set_enchantments levels and custom model data floats and colors, drawing uniformly from an IntRange or float range on provider fields, like rolls(1..3), with tests and docs. cadc186 6c96820 ad97bcf
  • feat(itemmodifiers, predicates, providers, slotsources): Accept predicate, item modifier, number provider and slot source IDs and tags in place of inline values, and remove the reference predicate, item modifier and slot source, with tests and docs. f5c697d cf15346 4a473b1 3f0e72c
  • feat(itemmodifiers): Accept providers in the set_ominous_bottle_amplifier amplifier and the set_custom_model_data colors, make the exploration_map destination a required structure list, accept item modifier IDs in modify_contents, and give set_loot_table a loot table ID without a block entity type, with tests and docs. 33352fc 93df865 6176f76
  • feat(loottables): Accept loot table IDs, lists and tags with expand in the loot_table entry, item IDs, lists and tags in the tag entry items, and add the missing loot context types, command_compute_* included, with tests and docs. 045123b 37f29f6
  • feat(loottables): Type the loot table type with the generated ContextKeySets registry, written as an ID, deprecating LootTableType, with tests and docs. 8b35ca7
  • feat(nbt): Write SNBT string values unquoted when the game reads them back as strings, with tests and docs. 4d74314
  • feat(oop): Add Entity.distanceTo writing the distance between two entities into a score in three commands, through their Pos and one compute, with tests and docs. 30c099e
  • feat(oop): Add setTo { } expressions and float factors on scoreboard entities through compute, with tests and docs. c1b9c4c
  • feat(oop): Make entity summon data the shared base of mannequins, display entities, interactions and item entities, with team, custom data, passengers, frozen ticks and invulnerableTime builders and the fall_distance and Air keys fixed, with tests and docs. d0dfcfd 22b05c9 36973e5
  • feat(optimization): Add opt-in passes hoisting repeated inline context providers and predicates into files, with tests and docs. 135114c b313143
  • feat(predicates): Accept damage type lists in damage tags, with tests and docs. 0b1cda3
  • feat(predicates): Replace block_state_property with match_block and write the block predicate nbt as a JSON object, which failed to encode, with tests and docs. 3951a1d
  • feat(providers): Add Kotlin operators building context int and float provider trees, with tests and docs. d608cb6
  • feat(recipes): Add the brewing recipe type, TransmuteResult with an optional id for crafting_transmute and crafting_special_mapextending, and make cookingtime required on the cooking recipes, with tests and docs. e8a5667 c88b49a 4c5b2e6
  • feat(trims): Replace the trim material asset_name and override_armor_assets with palette_id, typing the palettes moved to textures/palettes/trim, with tests and docs. 87f48ac
  • feat(villagertrades): Add maxUses, xp and reputationDiscount setters taking providers or plain numbers, TradeSet.amount taking a provider, and write wants and additional_wants as trade costs with an int provider count, with tests and docs. 86144d3 626ee90
  • feat(worldgen): Add int and float provider setters taking plain numbers to features, placement modifiers, dimension types, biome spawns, enchantment providers, block state providers, tree placers, carvers and play_sound, height provider setters taking a vertical anchor, the very_biased_to_bottom int provider and the relative_to_sea_level vertical anchor, with tests and docs. 3f1bbb7 e468c70 ff10246 3e9e068 0a293dd
  • feat(worldgen): Add the cuboid, random_chance and randomly_selected placement modifiers, replace random_offset with a per-axis offset, and require the value of count, count_on_every_layer, rarity_filter, height_range and the environment_scan max_steps, with tests and docs. 31aa6a3 5bb759f 7e77229 d38f9a6
  • feat(worldgen): Add the dimension_origin structure placement, with tests and docs. aa27894
  • feat(worldgen): Add the height_range and volume_match block predicates and the all_of, any_of, height_match and not rule tests, with tests and docs. b16f179 c05ed20 ce65aaf 1811343
  • feat(worldgen): Add the overlay, projected_random_patchy_square and fallen_tree features and inline placed features in the overlay, sequence and simple_random_selector lists, with tests and docs. e3077c7 ddff76c bca0a33
  • feat(worldgen): Add the root_placer of trees, the pale_moss, creaking_heart, place_on_ground, attached_to_logs and shelf_mushroom tree decorators, the poplar_trunk_placer and poplar_foliage_placer, and the end_podium feature, with tests and docs. 697fb08 491ce1f 27c2c4c
  • feat(worldgen): Add the sub, div, negate, lerp, floor, round, ceil, truncate, distance_to_point, log, pow, sign, slice and sqrt density functions, inline noise parameters and shiftX, shiftY and shiftZ on noise replacing shifted_noise, rename cache_once to cache without the other caches, and require the interpolated cell sizes, with tests and docs. 3a6c631 f364122 c0cc847 63828bb 76f6d46 b19be8e 2d2082d
  • feat(worldgen): Add the copy_properties_provider and random_block_provider block state providers, wrap any provider in rotated_block_provider with an optional direction, rename the provider types to their game names, and add block state provider files and references, with tests and docs. 84d9cdf b79eb17 6568024 e5ce86f
  • feat(worldgen): Rename configured carvers to carvers written to worldgen/carver, flatten their config, and replace lava_level, replaceable, debug_settings, y_scale and nether_cave with the 26.3 cave fields and canyon shape.y_scale, with tests and docs. 1707e79
  • feat(worldgen): Rename surface rules to material rules, write material_rule in noise settings and add the data-driven material_rule and material_condition files usable by reference, with tests and docs. 7831c95 6ff693b
  • feat(worldgen): Replace basalt_columns, basalt_pillar and glowstone_blob with the configurable stepped_column_cluster, single_block_pillar and random_neighbor_spread features, with tests and docs. 2a533b9 21da214
  • feat(worldgen): Replace the bed rule's explodes with destroy_on_use and destroy_on_leave, and add straw_bed_rule, with tests and docs. 50c9fd9
  • feat(worldgen): Replace the noise settings aquifer and ore vein toggles with aquifers and the ore_vein material rule, make spawn_target a list of points built with spawnTargetPoint { }, add debugFunctions, rename preliminarySurfaceLevel to chunkSurfaceLevel and remove the noise options' sizeHorizontal and sizeVertical, with tests and docs. f2f255b ee01b30 24dd27d 1649ce0 bc2212d 7b397ce
  • feat(worldgen): Require the placed feature of coral_claw and coral_tree, and remove the coral_mushroom, kelp, sea_pickle and seagrass features, with tests and docs. 80573cb
  • feat(worldgen): Write configured features to worldgen/feature with their fields next to type instead of in config, generating Features and FeatureArgument in place of ConfiguredFeatures and ConfiguredFeatureArgument. 4672068
  • feat(worldgen): Accept inline processor lists in the template and fossil features and single pool elements, with tests and docs. 3f26c7e

Bug Fixes

  • fix(commands): Write inline configured features, dialogs, loot tables, item modifiers, predicates and slot sources in their data pack shape, and the inline item modifier of /item modify and /item replace ... from as the function itself instead of a modifiers wrapper, with tests and docs. 97fe253 8816668
  • fix(components): Type the potion_contents component matcher with PotionOrTagArgument, since it matches potion IDs and not mob effects. ea8dfc4
  • fix(components): Write entity variant components under their real IDs like sheep/color instead of sheep_color, keep the namespace of custom component types, and write profile UUIDs as int arrays, with tests. 0314b44 2093399
  • fix(environmentattributes): Write the ambient_particles entry particle as particle like the game instead of options, with tests. 51a84ff
  • fix(helpers): Fix setToLookDirection, lookAlong and atan2 being off by half a block from centered integer coordinates, without moving the marker out of its chunk, with tests and docs. 82f97e8
  • fix(helpers): Type display width, height and view range as floats and add teleportDuration, write display transformations decomposed without mutating them, start the scale and translation builders from the current values, and write glow_color_override and text display background as RGB and ARGB ints, which the game read as nothing before, with tests and docs. 72fb22d ad7e30f cfa5c46 562f5f3
  • fix(itemmodifiers, slotsources): Write item modifier and slot source files as one object, wrapping several entries or a lone reference in a sequence or a group, with tests and docs. 383388d b3af444
  • fix(itemmodifiers): Type the set_stew_effect effect as a mob effect instead of a potion, with tests and docs. aad68bb
  • fix(kore): Skip unset elements when encoding NBT, so classes inheriting serializable properties from another module serialize on JS. b483717
  • fix(loottables): Write the archaeology loot context as archaeology like the game instead of archeology, with tests and docs. 77d3f4b
  • fix(nbt, serialization): Write whole floats and doubles with a decimal point on every platform in JSON and SNBT, and keep the numbers and strings of a mixed SNBT list, with tests. 2c2e081 79f7dbd
  • fix(publish): Declare the GPL-3.0 license of the LICENSE file in published POMs instead of MIT. f2161a3
  • fix(tradesets): Make amount(min, max) draw like amount(range), writing a constant for equal bounds and rejecting inverted ones, with tests. dddcc8c
  • fix(worldgen): Make the end spike crystal_beam_target optional, write the pillar centerX and centerZ keys vanilla reads and add the spike { } builder, with tests. 0af0f84
  • fix(worldgen): Write the keys vanilla reads: the delta feature contents, can_grow_through of the upwards branching trunk placer and mangrove root placer, the root placer above_root_placement, the environment_scan direction_of_search and the weighted random selector data, with tests. 22bf17b 6f364cd 52e1412 02b1f29 90a855e
  • fix(worldgen): Write the types vanilla reads: the geode crack_point_offset as an int, the huge fungus block states as plain block states, the speleothem cluster density, wetness and chance as float providers, the vegetation patches xz_radius as an int provider and multi-noise ranges as [min, max] arrays, and raise the root system and patch defaults to the schema minimum, with tests. 90b819e a5b1f19 794312c 34cdaad cc02937 69b4931

Performance improvements

  • perf(helpers): Compute sin, cos, sqrt, distanceSquared, parabola and the ScoreVector dot, cross, length, distance and normalize with compute commands, fixing normalize, with tests and docs. 0363c5d dfe37e3 03b1a0b 1c891b4 e9398b1 1ff4df7

Refactors

  • refactor(arguments): Make every slot range a slot written <name>.*, so ARMOR writes armor.* instead of the invalid armor, and keep indexing to the numbered ranges. 4b94da0
  • refactor(blocks, worldgen): Rename BlockState.name and the block parameter of simpleStateProvider, rotatedBlockProvider and the block material rule to id, and write block states with the id and properties keys, as a bare block ID when no property is set, reading both forms, with tests and docs. 06efef9 69d393b
  • refactor(colors, particles): Share one ParticleOptions model between /particle, enchantment effects and environment attributes, with namespaced IDs, packed int colors and every particle's options, and remove ColorAsDoubleArraySerializer, RGB.fromDoubleArray and the normalizedArray getters. cb9bf86 8ccc89f e694fe3
  • refactor(components): Remove the map_color component and replace swing_animation with attack_animation and interact_animation, moving SwingAnimationType to arguments.enums, with tests and docs. fa1e995 3b8044a
  • refactor(environmentattributes): Build ambient particles, ambient sounds, background music and bed rules only through builders, without hand-built entry instances. 3917261
  • refactor(generation): Name the root entries of generated path trees in SCREAMING_CASE like enum entries, Recipes.STONE next to Recipes.Brewing, TemplatePools.EMPTY and Noises.CALCITE. e0250e9
  • refactor(itemmodifiers, loottables, predicates): Write the item function and predicate discriminators as type, with several predicate conditions merged into an all_of, and replace the loot table, pool, entry and item function conditions and functions with a single condition and modifier, with tests and docs. 39f07aa fcc41e2 2699b78
  • refactor(recipes): Build special crafting types with RecipeTypes.CRAFTING_SPECIAL(group) instead of the CraftingSpecial object, drop the unused RecipeTypes.values list and give SmithingTrim the smithing_trim type. f3a1d2c
  • refactor(serializers): Read and write SNBT element names in snake_case like the data pack JSON, honoring JsonSerialName. 4b1af71 4974c52
  • refactor(villagertrades): Rename givenItemModifiers to givenItemModifier, which also takes an item modifier ID, with tests and docs. 08e3dc9
  • refactor(worldgen): Remove the desert_well, random_patch, nether_forest_vegetation, twisting_vines and weeping_vines features and the sculk_patch catalyst_chance and extra_rare_growths fields, with tests and docs. 0886237 fb4c0a8 4129ce0 830bee4
  • refactor(worldgen): Remove the biome spawn fields moved to the natural_mob_spawns and creature_world_gen_spawn_probability environment attributes, with tests and docs. fdfa128
  • refactor(worldgen): Rename the density function fields to input, left/right, value and noise, invert to reciprocal and end_islands to end_outer_islands, and replace y_clamped_gradient with gradient along any axis with a tiling mode, with tests and docs. d87344d 4ef59af aa3845c
  • refactor(worldgen): Require the random selector default and chances. 9c44ce3
  • refactor(worldgen): Reshape noise parameters into base_octave, base_amplitude, octave_count, normalize and amplitude_modifiers, sharing one NoiseParameters class between block state providers and writing octave_count from the amplitude modifiers when unset, with tests and docs. 64cc613 785f40e

Full changelog: https://github.com/Ayfri/Kore/compare/v2.16.0-26.2..v2.28.0-26.3

Minecraft 26.24

8 Oct 202619 days ago

2.16.0

MC 26.2Release

A fix-heavy release on top of 26.2, and the first one shipping with the Kore Playground: write Kore in the browser, see the generated pack update as you type, and download or share it, no project setup needed.

Most of the cycle went into a pass over the oop and helpers features that did not do what they said in game: Entity.onDeath never fired, cooldowns and timers ran 20 times too fast, the Inventory Manager wiped whole inventories every tick, and advancement events reset every advancement of the player. They all work now, along with a batch of JSON and command fixes the game rejected.

A few public helpers were removed or retyped while cleaning up the NBT utilities. The Migration notes list each one with the code to change.

What's new?

  • Playground: a full Kore IDE in the browser, with completion, hover docs and auto-import for kore, oop and helpers, live compilation, a pack explorer, zip download and shareable links.
  • Version Support and Debugging guides: how Kore versions map to Minecraft versions, what counts as breaking, and how to trace a game error back to your Kotlin code.
  • Footprint callouts: every helper and OOP doc page lists the objectives, storages, entities, forceloaded chunks, tick and load functions the feature adds to your pack.
  • Custom model data from scores: setCustomModelData floats take number providers.

Playground

Open kore.ayfri.com/playground, pick one of the examples (commands, text components, scoreboards, predicates, item modifiers, dialogs, sidebars, raycasts...) or write your own pack. Every edit recompiles on its own, the generated files show up in the explorer next to the editor, and the result downloads as a ready-to-install zip.

  • Completion follows the receiver of each DSL block, imports what you accept and shows the KDoc of every Kore declaration on hover.
  • The share button puts the whole snippet in the URL, and https://kore.ayfri.com/playground#example=hello-world opens an example directly.
  • Docs pages and the home page link to the matching example, so any snippet is one click away from running.

Custom model data from scores

itemModifier("model_from_score") {
	setCustomModelData {
		floats(sum(scoreNumber("charge", "#gun"), constant(0.5f)))
	}
}
Kotlin

Fixes worth knowing

  • Entity.onDeath fires: matching mobs are tagged and get a death loot table that keeps their vanilla drops, and only the handlers of the selectors that died run. Players and untyped entities are refused, since a loot table can't catch their death.
  • Cooldowns and timers convert durations to ticks (2.seconds lasted 2 ticks), count down on any entity holding a score instead of players only, and registerTimerWithBossBar fills its boss bar.
  • Inventory Manager stops clearing the whole inventory and offhand every tick, detects taken slots on 1.20.5+ item components, and works from a function { } inside a dataPack { }.
  • Advancement events revoke only their own advancement instead of advancement revoke @s everything.
  • Enchantments referencing a pack predicate load: the conditions are inlined, since the game validates enchantments without a resolver.
  • Text components: a styled first component no longer leaks its style onto the next ones, and extra and lore are always written as lists.
  • Optimizations keep score conditions out of limited and @p/@r/@n selectors and stop pruning empty functions still called by schedule, if function or macros.

Performance

  • Existence checks in optimized packs: if entity @e[...] gets limit=1 and stops at the first match, ~2000x faster with 8,192 entities.
  • Inventory Manager: item entities and the marker are found by tag instead of an nbt= scan, ~15x per item entity.
  • Score vectors: positions read off a marker instead of three NBT reads of the player, ~8x for a player position, ~3x for motion.

Migration notes

NBT helpers duplicating knbt are removed

String.nbt, stringifiedNbt, stringifiedNbtList, nbtArg, nbtText, the Iterable overloads of nbtListOf, the NbtListBuilder.addAll overloads and StringifiedNbt.encodeToSnbt are gone, as is MutableNbtCompound.

// Before
val name = "Steve".nbt
val snbt = stringifiedNbt { this["x"] = 1 }
val arg = nbtArg { this["x"] = 1 }
val list = nbtListOf(listOf(1, 2, 3))
val encoded = StringifiedNbt.encodeToSnbt(myValue)

// After
val name = NbtString("Steve")
val snbt = nbt { this["x"] = 1 }.toSnbt()
val arg = literal(nbt { this["x"] = 1 }.toSnbt())
val list = nbtListOf(1, 2, 3)
val encoded = encodeToSnbt(myValue)
Kotlin

data merge and data modify of a @Serializable class no longer wrap it in a {"<serial name>": ...} root, so code relying on that root needs updating.

setCustomModelData floats are number providers

The floats property is a ListOperation<NumberProvider>. The floats: List<Float> parameter of the builder still takes plain floats.

// Before
setCustomModelData { floats = ListOperation(listOf(1f, 2f)) }

// After
setCustomModelData { floats(constant(1f), constant(2f)) }
Kotlin

Book pages share one BookPage type

WritablePage and WrittenPage are aliases of BookPage<String> and BookPage<ChatComponents>, and their single parameter is gone: a page without a filtered value is written as its raw text.

// Before
WritablePage("Hello", single = false)

// After
WritablePage("Hello")
Kotlin

Durations of cooldowns and timers are real durations

registerCooldown, registerTimer and registerTimerWithBossBar convert their duration to ticks. A 2.seconds cooldown that ran 2 ticks now runs 40, so code that passed 40.seconds to get 2 seconds must pass the real duration.

// Before, worked around the bug
registerCooldown("dash", 40.seconds)

// After
registerCooldown("dash", 2.seconds)
Kotlin

Unimported loot DSL calls fail to compile

The loot table, item modifier and predicate builders carry a @LootDsl marker, so a functions { } or conditions { } written in an entry without its import fails to compile instead of landing on the enclosing pool. Import the entry-level function the compiler points at.

TimeNumber.asArg() is removed

// Before
time.asArg()

// After
literal(time.asString())
Kotlin

Changelog

New Features

  • feat(item-modifiers): Take number providers in set_custom_model_data floats through floats(...), so a float can come from a score, a storage or a sum of them, matching the vanilla codec. f915249

Bug Fixes

  • fix(chat-components): Write an empty root before a styled first component of a text list, so its style stops leaking onto the others, and always write extra and set_lore lines as lists. 434a347 b4cdc5f
  • fix(commands): Make score(target, objective) and its Relation overload ExecuteCondition members, so they compile without importing arguments.scores.score. ca98d05
  • fix(commands): Write the half-turn of place template as 180 and worldborder center with PosNumber coordinates. 88e97a5 c8d6789
  • fix(enchantments): Inline the conditions of every pack predicate an enchantment references, since the game refused to load one holding a reference condition. 78aafc3
  • fix(events): Revoke only the event advancement in the advancement-event dispatchers instead of advancement revoke @s everything. 5291c8c
  • fix(functions): List the callers of each generated function in # Called by comments when generateCommentOfGeneratedFunctionCall is on, instead of a comment returnRun also wrote with the flag off. b8bc35e
  • fix(generation): Write a Quilt license, which always threw. c279cf2
  • fix(helpers): Divide by the dominant axis in the 180-degree branches of AxisAngle4f.set(Matrix4f), which returned Infinity or a skewed axis. 45906cf
  • fix(helpers): Make the Inventory Manager stop wiping the whole inventory and offhand every tick, detect taken slots with if items on custom_data, only kill its own marker on load, and work from a function { } inside a dataPack { }. b13e50f f85c88c bb91d47
  • fix(item-modifiers): Omit options when enchantRandomly() gets no enchantment, and serialize the context source of copy_custom_data as {type: "minecraft:context", target}. 5252a95 98527a8
  • fix(loot-tables): Add a @LootDsl marker on the loot table, item modifier and predicate builders so an unimported entry functions or conditions fails to compile instead of landing on the enclosing pool. 597fc63
  • fix(oop): Convert cooldown and timer durations to ticks, count them on every entity holding a score, and fill the registerTimerWithBossBar boss bar every tick. 1163b6c 71219ca 6d89dcb
  • fix(oop): Make Entity.onDeath fire by tagging the matching mobs and giving them a death loot table that keeps their vanilla drops, running only the handlers of the selectors that died, and refuse players and untyped entities. 68a4721
  • fix(optimization): Stop hoisting score conditions into limited or @p/@r/@n selectors and pruning empty functions still named by schedule, if function or macros, flatten run execute chains and give existence tests limit=1. 77ea389

Performance improvements

  • perf(helpers): Find Inventory Manager item entities by tag instead of an nbt= selector (~15x per item entity), and read ScoreVector positions off a marker instead of three NBT reads of the player (~8x). 50bf184 f2360cf

Refactors

  • refactor(item-components): Make WritablePage and WrittenPage aliases of one generic BookPage, dropping their single flag. 56d77f2
  • refactor(nbt): Drop the NbtTagUtils helpers duplicating knbt and the unused MutableNbtCompound, so data merge/modify of a serializable class stops wrapping it in a {"<serial name>":...} root. 5f6d81e

Documentation

  • docs(contributing): Replace reference-style links with inline links. 46ff362
  • docs(guides): Add Version Support and Debugging pages covering the version scheme, breaking changes, deprecations, generated function names, tracing game errors back to Kotlin, Spyglass and PackTest. 83ec28f
  • docs(website): Add a Footprint callout to every helper and OOP feature, and point the docs to the Features, Updates and playground pages. d588ec4 6209d73 19e2267

Full changelog: https://github.com/Ayfri/Kore/compare/v2.15.0-26.2..v2.16.0-26.2

29 Sept 202627 days ago

2.15.0

MC 26.2Release

A feature release on top of 26.2, built around three things: in-game UI helpers, a correctness sweep of everything Kore writes, and reproducible packs. Menus built from dialogs, server-style sidebars and runtime score vectors join the helpers, trial spawner configurations and multi-noise parameter lists join the data-driven features, and every file the game rejected in 26.2 now loads.

Two builds of the same code now produce the same pack: generated functions, event handlers, UUIDs and structure set salts are derived from their content instead of identity hash codes or random numbers. Cold starts got a lot cheaper along the way, the first tag of a pack dropping from 101ms to 3ms and the first advancement trigger from 61ms to 4ms.

A few APIs changed behavior or name, mostly because the old one let you write something wrong without noticing. The Migration notes list each one with the code to change. The website also got a new homepage, a Features page and a redesigned Updates timeline.

What's new?

  • Menus: in-game GUIs built from dialogs, with buttons running Kotlin-declared commands for every player (operator or not), sub-pages, links, the pause screen and the Smithed data pack menu.
  • Sidebars: Sidebar replaces ScoreboardDisplay, with right-aligned values, live scores, conditional lines and a refresh() rewriting only the lines that can change.
  • Score vectors: runtime 3D vectors on scoreboards, reading positions, motion and look directions, with dot and cross products, exact length, normalize, teleports and motion. The scoreboard math engine behind them is rewritten around shared functions.
  • Trial spawners: trialSpawner configurations with spawn potentials, equipment, custom spawn rules and reward loot tables.
  • Multi-noise parameter lists: give a vanilla biome layout its own id and point any multiNoise biome source at it.
  • Execute and selectors: inverted { } flips the checks of a condition block, the selector type accepts entity type tags, and the kick command is in.
  • Reproducible packs: every generated name is a hash of its content, hashedGeneratedFunction gives your own builders the same naming, and DataPack.entityUUID gives build-stable UUIDs.
  • Gradle plugin AOT cache: koreBuild runs your entry point on a JDK AOT cache trained by its first run.

Menus

val kits = menu("kits", "Choose your kit", Color.GOLD) {
	text("Your inventory is replaced by the kit.")

	button("Warrior") {
		clear(self())
		give(self(), Items.IRON_SWORD)
		give(self(), Items.SHIELD)
	}

	button("Archer") {
		clear(self())
		give(self(), Items.BOW)
		give(self(), Items.ARROW, 32)
	}

	page("Help") {
		text("Pick a new kit after each death.")
		link("Rules", "https://example.net/rules")
	}

	pauseScreen = true
}

function("open_kits") { kits.open() }
Kotlin

A dialog button only runs commands with the clicking player's permissions, and /function needs operator rights. So each button runs trigger <namespace>.menu.<name> set <n> instead, and a generated tick function runs the matching button function for whoever clicked. A menu is a dialog like any other, so it opens from a chat link too:

tellraw(allPlayers(), textComponent("[Choose a kit]", Color.GREEN) {
	clickEvent { showDialog(kits.dialog) }
})
Kotlin

smithed = true lists the menu behind the shared "Data Packs..." pause screen button of the Smithed convention, next to every other compatible pack.

Sidebars

val lobby = sidebar("lobby") {
	title("Sky Wars", Color.GOLD)
	line("Map: Floating Isles")
	emptyLine()
	line("Players", value = scoreComponent("players_alive", literal("#game")))
	line("Kills", Color.RED, scoreComponent("kills", literal("#top")))
	emptyLine()
	line("play.example.net", Color.YELLOW)
}

load { lobby.create() }
tick { lobby.refresh() }
Kotlin

Score numbers are always hidden, values are drawn with numberformat fixed. refresh() only rewrites the lines holding score, selector or NBT components, so calling it every tick stays cheap. Lines can also be conditional or swapped at runtime:

sidebar("event") {
	line("Double XP active!", Color.GREEN) {
		visibleIf { score(literal("#event"), "double_xp", rangeOrInt(1)) }
	}
}

function("switch_map") {
	lobby.setLine(0, textComponent("Map: Nether Fortress"))
}
Kotlin

Score vectors

val math = registerMath()

function("dash") {
	val dash = math.vector("dash", player)
	dash.setToLookDirection(self())
	dash *= 3
	dash.teleport(self(), TeleportMode.RELATIVE)
}

function("launch_pad") {
	launch.set(0.0, 1.2, 0.0)
	launch.applyAsMotion(self())
}

function("homing_missile") {
	toTarget.setTo(targetPos)
	toTarget -= missilePos
	toTarget.normalize()
}
Kotlin

Components are fixed-point, 1500 meaning 1.5 blocks at the default scale. length, distanceTo and normalize are exact to the float: the length comes from the game's own decomposition of a text_display transformation, and normalize teleports a marker one block along facing, instead of approximating a square root on scoreboards.

Trial spawners and parameter lists

val skeletonArchers = dp.trialSpawner("skeleton_archers") {
	simultaneousMobs = 3f
	simultaneousMobsAddedPerPlayer = 0.5f
	ticksBetweenSpawn = 20
	totalMobs = 8f

	spawnPotential(EntityTypes.SKELETON, weight = 3) {
		equipment(LootTables.Equipment.TRIAL_CHAMBER_RANGED, 0f)
	}
	spawnPotential(EntityTypes.STRAY) {
		equipment(LootTables.Equipment.TRIAL_CHAMBER_RANGED, mapOf(EquipmentSlot.HEAD to 0.5f))
	}
}

dp.trialSpawner("ominous_breezes") {
	itemsToDropWhenOminous = LootTables.Spawners.TrialChamber.ITEMS_TO_DROP_WHEN_OMINOUS
	lootTableToEject(LootTables.Spawners.Ominous.TrialChamber.KEY, weight = 3)
	lootTableToEject(LootTables.Spawners.Ominous.TrialChamber.CONSUMABLES, weight = 7)
}
Kotlin
val skylandsBiomes = dp.multiNoiseBiomeSourceParameterList("skylands", BiomePresets.OVERWORLD)

dp.dimension("skylands", type = myDimType) {
	noiseGenerator(settings = NoiseSettings.FLOATING_ISLANDS, biomeSource = multiNoise(skylandsBiomes))
}
Kotlin

Conditions, selectors and commands

function("checks") {
	execute {
		ifCondition { inverted { score(self(), "frozen", rangeOrInt(1)) } }
		run { say("not frozen") }
	}

	kill(allEntities { type = Tags.EntityType.RAIDERS })
	kick(allPlayers(), "Server restarting")
}
Kotlin
execute unless score @s frozen matches 1 run say not frozen
kill @e[type=#minecraft:raiders]
kick @a Server restarting
Mcfunction

inverted { } negates a reusable condition block without rewriting it, and Entity.isPlayer now matches EntityTypes.PLAYER, which it never did.

Reproducible packs

val onClick = hashedGeneratedFunction("on_click") {
	say("clicked")
}
// data/<namespace>/function/generated_scopes/on_click_<hash>.mcfunction, the same name on every build

function("spawn_marker") {
	val uuid = datapack.entityUUID("my_marker")
	summon(EntityTypes.MARKER) { this["UUID"] = uuid.toNBTIntArray() }
}
Kotlin

Generated functions are named generated_<hash> after their body, and so are load_<hash>, tick_<hash>, schedule_<hash>, events, cooldowns, timers, game states and scheduler wrappers. The same body always gets the same name, on every run and platform, and two builders producing the same body share one function. entityUUID hashes the pack name, the key and how many times the key was asked for, so two markers get two UUIDs and a rebuild gives both the same ones again.

Performance

  • First tag of a pack: 101ms → 3ms, through a generated when instead of a map of 148 lambdas.
  • First advancement trigger: 61ms → 4ms and 186 → 9 loaded classes, sealed families now loading only the serialized subtype (particles 18ms → 9ms, actions 16ms → 9ms).
  • First selector: 163ms → 53ms, each render ~1.3µs → ~0.5µs, rendered directly instead of through an escaped JSON tree.
  • First text component: 76ms → 24ms.
  • Pruning unreferenced generated functions: 1099ms → 4.5ms on a 1,750 function pack, registering them 178ms → 3ms.
  • Disabled Optimization(): 9.3ms → 1.2ms.
  • File writes: ~7 fewer filesystem calls per file (a real pack's warm generation 100ms → 66ms), no byte-by-byte copy on OPFS and fetch.
  • Kotlin/JS lazy serializers: 40ms → 12ms decoding 20,000 values.
  • Gradle plugin: a small pack's generation ~1s → ~0.37s with the AOT cache.
  • Artifact size: kore 9,706 → 8,387 classes, its JS library 24.4 MB → 23.4 MB.

Migration notes

Every breaking change of this cycle, with the code to change on your side.

ScoreboardDisplay becomes Sidebar

The old helper created and displayed itself where it was declared. A Sidebar is declared once, then created, refreshed or changed from any function.

// Before
function("setup") {
	scoreboardDisplay("lobby") {
		displayName = textComponent("Sky Wars", Color.GOLD)
		appendLine("Map: Floating Isles")
		emptyLine()
		appendLine(textComponent("Double XP active!", Color.GREEN)) {
			condition { score(literal("#event"), "double_xp", rangeOrInt(1)) }
		}
		hideValues()
	}
}

// After, score numbers are always hidden
val lobby = sidebar("lobby") {
	title("Sky Wars", Color.GOLD)
	line("Map: Floating Isles")
	emptyLine()
	line("Double XP active!", Color.GREEN) {
		visibleIf { score(literal("#event"), "double_xp", rangeOrInt(1)) }
	}
}

load { lobby.create() }
tick { lobby.refresh() }
Kotlin

copyFrom and copyTo copy the right way

Both were swapped: copyFrom wrote into the source and copyTo read from the target. Code written around the swap has to be flipped back.

val kills = player("Ayfri").getScoreEntity("kills")
val best = fakePlayer("best").getScoreEntity("kills")

best.copyFrom(kills) // 2.15: best takes the value of kills. 2.14 did the opposite
best.copyTo(kills)   // 2.15: kills takes the value of best
Kotlin

ChatComponents.plus and the display maths return new values

+ used to append to its left side, so a shared prefix piled up across messages. It now returns new components, like the Quaternion and Matrix operators and conjugate of the display helpers.

val prefix = textComponent("[Kore] ", Color.GOLD)

tellraw(allPlayers(), prefix + text("Welcome"))
tellraw(allPlayers(), prefix + text("Goodbye"))
// 2.14: the second message read "[Kore] Welcome Goodbye"
// 2.15: "[Kore] Goodbye", prefix never changes

// Code relying on the mutation reassigns instead
var message = textComponent("Players: ")
message += text("Ayfri")
Kotlin

bundlerContents becomes bundleContents

The old name wrote a minecraft:bundler_contents key the game doesn't know.

// Before
bundlerContents { items { /* ... */ } }

// After
bundleContents { items { /* ... */ } }
Kotlin

stopSound takes sound events

It took sound file paths, which /stopsound never matches.

// Before
stopSound(self(), PlaySoundMixer.MASTER, Sounds.Mob.Bat.TAKEOFF)

// After
stopSound(self(), PlaySoundMixer.MASTER, SoundEvents.Entity.Bat.TAKEOFF)
stopSound(self(), sound = SoundEvents.Entity.Bat.TAKEOFF) // stopsound @s * minecraft:entity.bat.takeoff
Kotlin

test verify takes one test or a selector

Like vanilla, verify checks a single test or everything a test selector matches.

test {
	// Before
	verify(TestInstanceArgument("test1", "pack"), TestInstanceArgument("test2", "pack"))

	// After
	verify(TestInstanceArgument("test1", "pack"))
	verify(testSelector("pack:test*"))
}
Kotlin

Loot entry functions and conditions need their own import

The loot table, item modifier and predicate builders are DSL-scoped now. An entry functions { } resolved without its import used to land on the enclosing pool silently, it now fails to compile.

import io.github.ayfri.kore.features.loottables.entries.functions

lootTable("diamonds") {
	pool {
		entries {
			item(Items.DIAMOND) {
				functions { setCount(2f) } // on the entry, not on the pool
			}
		}
	}
}
Kotlin

Generated function paths and file collisions

Generated function names change once to their <prefix>_<hash> form, then stay stable. Update anything that references a generated path by hand. Two files claiming one path with different contents now throw instead of one being dropped:

function("init") { say("a") }
function("init") { say("b") } // 2.15: IllegalStateException at generation. 2.14 silently kept one of them
Kotlin

Removed, with no replacement

  • io.github.ayfri.kore.helpers.displays.maths.Vec3f, a duplicate of io.github.ayfri.kore.arguments.maths.Vec3f: change the import.
  • Tag.tagClass, which was written on every typed tag but never read.
  • String.unescape, which turned an escaped \n into n.

Kore is now built with Kotlin 2.4.20.


Changelog

New Features

  • feat(advancements): Add the location conditions to the anyBlockUse and defaultBlockUse triggers. 3956b52
  • feat(arguments): Accept entity type tags in the selector type option, and fix Entity.isPlayer which never matched EntityTypes.PLAYER. 35280ca
  • feat(arguments): Add hashedUUID and DataPack.entityUUID, build-stable UUIDs unique per pack, key and occurrence. 96cd1a4
  • feat(chat-types): Add click_event, hover_event and shadow_color to chat type styles. b65f397
  • feat(commands): Add ExecuteCondition.inverted { } and the kick command. eedb943 9659fe0
  • feat(gradle-plugin): Run the datapack entry point on a JDK AOT cache trained by the first koreBuild, with an aotCache toggle. 9d72f57
  • feat(helpers): Add the dialog-based Menu helper with trigger-driven buttons, sub-pages, links, pause screen and Smithed data pack menu support. c06e26c
  • feat(helpers): Add notEqualTo and runUnless to state delegates. 7c94ac0
  • feat(helpers): Rewrite the scoreboard math engine around shared functions and add runtime ScoreVectors. c223d6c
  • feat(helpers)!: Replace ScoreboardDisplay with a Sidebar helper supporting right-aligned values, live refreshes and conditional lines. e3dc1d7
  • feat(item-modifiers): Add a setName(ChatComponents) overload so textComponent() results and joined components work. 1f8173d
  • feat(trial-spawners): Add trial spawner configurations with spawn potentials, equipment, custom spawn rules and reward loot tables. f80c6fb
  • feat(worldgen): Add multi-noise biome source parameter lists and let multiNoise reference them. 103820c

Bug Fixes

  • fix(advancements): Type the killMobNearSculkCatalyst entity as EntityOrPredicates like the other kill triggers. 87d9e91
  • fix(arguments, colors): Fix Vec2/Vec3 maths, print numbers without scientific notation, floor negative block positions, render Int positions without decimals, widen Floats through their shortest form (0.2, not 0.20000000298023224), fix the WEAPON and PLAYER.CRAFTING slot ranges, lowercase DisplaySlots.sidebarTeam colors, round ARGB.fromRGBAArray channels and stop Color aliases being null depending on initialization order. ceeeee8 40e6546 c596ee2 90084e4 f6b649c 1221b37 c508f73
  • fix(bindings): Parse GitHub, Modrinth and CurseForge responses with kotlinx.serialization instead of regexes that never matched real responses, pick the newest datapack file, URL-encode slugs and write cached files atomically. ca1e7f4 5868a9b
  • fix(build): Expose kotlinx-io and kotlinx-serialization as api dependencies of kore, since Path and Json are part of its public API. d5ac7d7
  • fix(chat-components, components, nbt): Write lore and book pages as text components and book titles as filterable strings, shadow_color as an ARGB int, escape backslashes and line breaks in SNBT strings, make ChatComponents.toComponent stop overwriting the first component's extra, and serialize user subclasses of CustomComponent. 19b0a19 b8f0083 bdb1da1 31be25b f86e24b
  • fix(chat-components, helpers)!: Make ChatComponents.plus, the Quaternion and Matrix operators and conjugate return new values instead of mutating their operands, and fix Quaternion.length and Transformation.interpolate/invert. 4365a36 9746cf7
  • fix(commands, functions)!: Keep namespaced ids in function(name), truncate block positions in every /item form, serialize the inline LootSource.fish loot table, set the run target of named execute { run(name) { } } blocks, fill skipped playSound arguments with the game defaults, escape line breaks in commands, make test verify take one test or selector, stopSound take sound events and stopWatch(id) resolve inside dataPack { function { } }. b915276 c06b656 0a9dfaa 0d34d2c fcba4dc 3ed97d9 0879c90 9659fe0 ce54861
  • fix(components)!: Rename the bundlerContents matcher to bundleContents, which writes the minecraft:bundle_contents key the game knows. 5bff149
  • fix(datapack)!: Throw when two files claim one path with different contents, write the startDebug() markers again, run the enabled optimization passes in exportAsStrings() like generate(), and route every log through a new KoreLogger. 5c5b99e 261b80b
  • fix(files, generation): Fix merging with other packs replacing the tick tag and crashing on .zip packs, reject zip entries escaping the extraction folder, close every file stream and create temporary directories with a random suffix. a7b9459 aef89b6
  • fix(functions, helpers, oop, worldgen)!: Make packs reproducible, deriving generated function, event, cooldown, timer, game state, scheduler and slot listener names, display and mannequin UUIDs and default structure set salts from content, and fix two multi-line returnRun sharing a file and the dynamicRunCommand and InventoryManager double generation. c24eceb 336ecc4 fc6f409 1a600e3 78e6f06
  • fix(gradle-plugin): Reject pack names that would make linking or koreClean hit a whole target folder, and refuse to wipe an output directory containing the project. 0278c22
  • fix(helpers): Write display entity brightness as sky, billboardMode as billboard and text display text as a component. f332d72
  • fix(helpers, oop): Keep the once-per-pack setup of cooldowns, timers, game states, events, dynamic strings, math and raycasts in a DataPack.state store instead of global maps, number inventory managers per pack and make removeClickDetectors remove the right objectives. ca4dc9f 43da27f
  • fix(loot-tables)!: Add a @LootDsl marker on the loot table, item modifier and predicate builders so an unimported entry functions or conditions fails to compile instead of landing on the enclosing pool. bc094e9
  • fix(oop)!: Copy into the receiver in ScoreboardEntity.copyFrom and into the target in copyTo, both were swapped. da681a7
  • fix(recipes): Write the cooking time as cookingtime, and add a namespace parameter to every recipe builder and a category to shaped, shapeless and cooking recipes. 05e2ff5
  • fix(sulfur-cube-archetype, trim-materials, trims, variants, worldgen): Write the fields 26.2 requires, the mob variant baby_* assets and wolf step_sound, bare trim palette names with override_armor_assets, the dimension type has_ender_dragon_fight, the sulfur cube sound_settings and trim pattern asset_ids as ids. b366a7f 66d2903 6ba599a 96d2d8c 0d77152
  • fix(tags): Add to the tag already registered under the same name instead of registering a second one the generator dropped, which lost every load, tick, setTag and event handler entry after the first. e05b105

Performance improvements

  • perf(bindings, generation, optimization): Create each output directory once per generation, index every namespaced id once and prune unreferenced generated functions through a worklist, hand OPFS and fetch the Int8Array a Kotlin/JS ByteArray already is, and drop the unused serializer annotation of ~1,300 generated enums. 04604d9 adb9667 5479c18 9ec4c89 2bf85a5
  • perf(chat-components, optimization, selectors, serializers, tags): Cut the cold-start cost of the first command, creating tag arguments through a generated when instead of 148 lambdas, serializing sealed families through a KSP-generated SealedDispatcher that loads only the serialized subtype, rendering selectors directly instead of through a JSON tree, building the ChatComponents decoder lazily, creating the default optimization passes on first access and reading lazy values through .value on Kotlin/JS. 67fcde6 c92ceb4 bdee8ce 2a7336e 1891fba 96e2357 87577fd

Refactors

  • refactor(helpers)!: Replace the duplicate displays Vec3f with the core one. 1005065
  • refactor(zip): Inflate zip entries with java.util.zip on the JVM, keep a bounds-checked pure-Kotlin inflater for JS, and read every zip in bindings through Kore's readZipEntries, dropping the kompress dependency. c89290a

Documentation

Full changelog: https://github.com/Ayfri/Kore/compare/v2.14.0-26.2..v2.15.0-26.2

7 Sept 2026last month

2.14.0

MC 26.2Release
kore-2 14 0-26 2-banner

A feature release on top of 26.2, built around three things that were missing from the datapack loop: string manipulation at runtime, a Gradle plugin to get the pack in game without leaving the editor, and whole-pack optimization passes that clean up what the DSL generated.

Nothing here is breaking. Everything is opt-in: an unused module generates no mcfunction at all.

What's new?

  • Dynamic Strings: a kotlin.String-shaped API over NBT storage. substring, split, join, replace, trim, padStart, uppercase, indexOf, reverse, plus a KoreStringList for the list side. Operators (+=, -=, *=) and a build { } DSL on top, results coming back as scoreboard scores.
  • Gradle plugin: id("io.github.ayfri.kore") adds koreBuild, koreLink, koreReload, koreRun, koreClean and koreWorlds. Runs your entry point, copies the pack into your worlds, and reloads a running server over RCON.
  • Optimization passes: seven whole-pack passes running right before the pack is written, pruning dead functions, shortening execute chains, hoisting score conditions into selectors, sorting selector arguments and merging duplicated functions.
  • Lantern Load: lanternLoad { } generates the whole convention, version scores on load.status and runtime dependency guards, so a pack can depend on Bookshelf or Smithed and be depended on in return.
  • Typed NBT paths: NbtPath replaces interpolated path strings, and resolveNbt writes one tree mixing literals and runtime scores.
  • Score arithmetic: *=, /=, %=, setTo, minWith, maxWith and swapWith between score handles and delegated scores, plus a FakePlayer entity for #-prefixed holders.

Dynamic strings

fun DataPack.hello() {
	registerDynamicStrings()

	val greeting = dynamicString("greeting")
	val buffer = dynamicString("buffer")

	function("greet") {
		greeting.set("  Hello, WORLD  ")
		greeting.trim()
		greeting.lowercase()
		greeting += '!'      // "hello, world!"

		buffer.build {       // "kore says: hello, world!"
			+"kore says: "
			+greeting
		}
		tellraw(allPlayers(), buffer.asChatComponents())
	}
}
Kotlin

A datapack cannot return a value, so every helper that computes something writes it into a fake-player score and returns a DynamicStringResult, which is a ScoreboardEntity. Predicates all use the same 1 / 0 convention:

(greeting contains "kore").then { tellraw(allPlayers(), textComponent("found")) }
(greeting startsWith "mine").otherwise { buffer.setFrom(greeting) }

bar.repeat(greeting.length())            // as many bars as characters
myScore.copyFrom(greeting.indexOf("="))  // a result feeds the whole scoreboard DSL
Kotlin

Splitting, joining and the list primitives round-trip a list through a single string, which is how a list fits in an item name, a sign line or one storage field:

val tokens = koreStringList("tokens")

greeting.split(",", tokens)  // ["a", "b", "", "c"], empty tokens preserved
tokens.join(",", csv)        // back to "a,b,,c"

tokens.forEach(current) {
	tellraw(allPlayers(), current.asChatComponents())
}
Kotlin

Scores convert in both directions, so a formatted counter needs no score chat component:

label.setFrom(kills)      // "7"
label.padStart(3, '0')    // "007"
label.prepend("Kills: ")  // "Kills: 007"
input.toScore(kills)      // "42" -> the score 42
Kotlin

Gradle plugin

plugins {
	kotlin("jvm")
	id("io.github.ayfri.kore") version "2.14.0-26.2"
}

kore {
	mainClass = "com.example.MainKt"
	packName = "my_pack"
	worlds = listOf("My World")
}
Kotlin
gradlew koreRun --continuous
Bash

Every save regenerates the pack, copies it into the worlds and reloads the running server over RCON, with no alt-tab at all.

Optimization passes

dataPack("mypack") {
	configuration {
		optimization()
	}
}
Kotlin

They are disabled by default, since a pass deletes content. Writing the block runs every built-in pass in order and prints one summary line each, [kore:prune-empty-functions] pruned 12 empty functions and 4 calls to them.

# before hoist-conditions-into-selectors
execute as @e[type=marker] if score @s timer matches 1 run say hi
# after
execute as @e[type=marker,scores={timer=1}] run say hi
Mcfunction

reorder-selector-arguments is the same idea applied to the selector itself: @e[nbt={...},type=marker] deserializes the NBT of every entity in range before checking the type, while @e[type=marker,nbt={...}] reads it for markers only. Same result set, so the reordering is free.

Lantern Load

dataPack("my_pack") {
	lanternLoad {
		version(1, 2, 3)
		dependency("bs.math", 3, 1)

		load {
			say("my_pack loaded")
		}
	}
}
Kotlin

Your version lands on load.status as three fake players, and each dependency generates a runtime guard following the ecosystem rule, major equal and minor at least the requested one:

# my_pack:load/resolve
execute if score bs.math.major load.status matches 3 if score bs.math.minor load.status matches 1.. run function my_pack:load/init
Mcfunction

init runs only when every guard passes, so the pack never half-initializes against a missing library.

Typed NBT paths and score resolution

val enchantments = nbtPath("equipment") / slot / "components" / "minecraft:enchantments"
// equipment.mainhand.components."minecraft:enchantments"
Kotlin

resolveNbt declares a tree once and emits both halves of it, the literal data modify and one execute store result per runtime score:

resolveNbt(storage("kore", "shop"), nbtPath("offer")) {
	this["item"] = "minecraft:diamond"
	this["price"] = price
	compound("meta") {
		this["featured"] = true
		this["stock"] = stock
	}
}
Kotlin
data modify storage kore:shop offer set value {item:"minecraft:diamond",meta:{featured:1b}}
execute store result storage kore:shop offer.price int 1.0 run scoreboard players get #price shop
execute store result storage kore:shop offer.meta.stock int 1.0 run scoreboard players get #stock shop
Mcfunction

Score arithmetic and fake players

function("score_math") {
	val score = player.getScoreEntity("score")
	val kills = player.getScoreEntity("kills")

	score += kills
	score /= kills      // floored division, as vanilla does
	score minWith kills // keeps the smaller of the two
	score swapWith kills

	score /= 2  // reads from a fake-player constant in kore_constants
}

function("next_wave") {
	val wave = fakePlayer("wave").getScoreEntity("game_state")
	wave += 1
}
Kotlin

A fake player has no entity behind it, so asSelector() throws instead of emitting @e[name=#wave], which matches an entity custom name and would silently target nothing. Score APIs go through asScoreHolder() and accept one.


Changelog

New Features

  • feat(oop): Add the dynamic strings module, DynamicString and KoreStringList over NBT storage, with operators, the build { } DSL, expression forms, the unified DynamicStringResult, multiplatform sources and a fully configurable runtime through DynamicStringConfig. 32c7801 8fa481c a3983ca 2116576 cc9631e 0e0d65d 4069051
  • feat(oop): Accept a DynamicString operand in replace, replaceFirst and split, a score-driven count in repeat, padStart and padEnd, and convert to and from a scoreboard score with setFrom, appendFrom, prependFrom and toScore. 5821058 6b0c954
  • feat(oop): Add the join operation concatenating a KoreStringList into a DynamicString with a separator, prefix and postfix. 4692fd8
  • feat(gradle-plugin): Add the io.github.ayfri.kore Gradle plugin running a datapack entry point, linking it into worlds and reloading over RCON, published to Central and the Gradle Plugin Portal on the shared version. 957c6b0 b02fa8a
  • feat(kore): Add opt-in whole-pack optimization passes, simplifying execute chains, hoisting score conditions, sorting selector arguments, merging duplicated functions, pruning empty and unreferenced generated ones and linting unreachable code. a2c5c66 bb32196
  • feat(kore): Add lanternLoad { } generating the Lantern Load boilerplate, version scores and dependency guards. 6977f33
  • feat(helpers): Add typed NbtPath paths, resolveNbt score resolution, and arithmetic between delegated scores. 6ca9be4
  • feat(kore): Add String.toNbt and String.toNbtTag to parse SNBT text back into tags. fdc7be2
  • feat(oop): Make ItemStack.toNbt public so a stack can be written into any NBT target. 40afa11

Bug Fixes

  • fix(oop): Add FakePlayer and route score APIs through Entity.asScoreHolder, so fake holders stop emitting @e[name=...]. abff7a4
  • fix(predicates): Annotate id in DamageTagPredicate with ArgumentSerializer. fcde15c

Performance improvements

  • perf(serializers): Skip the KSP rounds after the first and resolve supertypes through a shared cache in SerializerMapProcessor. e44424b
  • perf(utils): Hoist the per-call Regex instances out of snakeCase, handleMacro, macro name validation and unescapeChatComponent. f673376

Refactors

  • refactor(kore): Extract the entity-argument rewrite of an inlined execute command into inlineTargets. 23b0219

Documentation

  • docs(website): Add the Dynamic Strings page, structured around concepts, cost tiers, the operator forms and the scoreboard-result convention, with a typewriter dialogue box and a config-line parser as end-to-end examples. 47182c7 6c4242d 0b226a7 cbe2fcc 96fe3ec 17271d6 1b56ba5 94c6d99
  • docs(oop): Add before/after examples to the KDoc of every dynamic string operation. af011c5
  • docs(website): Add the Gradle plugin guide and document the shared publication version. ce52956
  • docs(website): Add the Optimization guide, document the seven passes and the order they run in, and list the optimization option on the configuration page. 7c02dee a31a936
  • docs(website): Add the Lantern Load guide covering load order, versioning and dependency guards. a589e76
  • docs(website): Use the current gamerule names in the dynamic strings, test features and world events pages. 2b92e0b 038994b

Full changelog: https://github.com/Ayfri/Kore/compare/v2.13.1-26.2..v2.14.0-26.2

24 Aug 20262 months ago

2.13.1

MC 26.2Release

Welcome to Kore 26.2!

kore-2 13 1-26 2-banner

Kore 26.2 is the cycle where the library stopped being JVM-only, and where most of the data-driven DSL got a serious retype.

It started on the tail of 26.1 with a Kotlin 2.4 upgrade and a multiplatform port, then turned into a long pass over worldgen and predicates: scoped builders everywhere, vanilla names everywhere, and a lot of fields fixed to actually match the JSON the game reads. On top of that, the new 26.2 content landed as it came: sulfur cubes, speleothems, geysers, and the usual batch of item component changes.

This cycle is also the most breaking one in a while. Nearly every rename here exists because the old API let you write something the game refuses, or because a global function polluted autocomplete in places it had no business being. The migration is mostly mechanical, and the examples below show the before and after.

What's new?

The big stuff this cycle was:

  • Multiplatform Support: kore, oop, helpers and bindings now target JVM and JS (browser + Node.js) at the same coordinates, powered by a pure-Kotlin ZipReader/ZipWriter and a PlatformIO abstraction (OPFS in the browser). org.joml and kotlin-reflect are gone as dependencies.
  • Kotlin 2.4: no more -Xcontext-parameters compiler argument, and java.util.UUID is replaced by the stable multiplatform kotlin.uuid.Uuid.
  • Worldgen: density functions, surface rules, carvers, processor lists, template pools, structures, block predicates, state providers, vertical anchors and height providers all moved to scoped builders, so autocomplete only offers what is valid in each context. New Providers and Carvers pages came with it.
  • Predicates: every sub-predicate now carries its vanilla *Predicate name, serialization is checked against vanilla-mcdoc, item sub-predicates moved to the component matchers, and score holders became a sealed ScoreProvider.
  • 26.2 content: sulfur_cube_archetype with explosion, contact damage, knockback and sounds, the speleothem rename, geyser particles, the sequence, template, weighted_random_selector and random_patch configured features, and the interval_select density function.

Code examples

Here is what the biggest 26.2 changes look like in practice.

Multiplatform datapacks

kotlin {
	jvm()
	js { browser(); nodejs() }
}

// works on every target
val zipBytes: ByteArray = pack.generateZipBytes()

// JVM/Node only, real filesystem
val datapack = exploreDatapackZip(zipBytes, "uploaded_pack.zip")
Kotlin

Scoped worldgen builders

Configured features, carvers and surface rules are built inside their own scope instead of loose global functions, so autocomplete only offers what is valid where you are.

// Before: global functions, the name is a positional argument of an outer call
configuredFeature("ore_iron", ore(size = 9, discardChanceOnAirExposure = 0.0) {
	targets(target(tagMatch(BlockTags.STONE_ORE_REPLACEABLES), blockState(Blocks.IRON_ORE)))
})
configuredFeature("bamboo_feature", bamboo(probability = 0.2))

// After: one scope, one method per feature type, the name is the first parameter
configuredFeatures {
	ore("ore_iron", size = 9, discardChanceOnAirExposure = 0.0) {
		targets { target(blockState(Blocks.IRON_ORE)) { target = tagMatch(BlockTags.STONE_ORE_REPLACEABLES) } }
	}
	bamboo("bamboo_feature", probability = 0.2)
}
Kotlin
// Before: surface rules built as nested sequence(condition(...), ...) calls
noiseSettings("overworld") {
	surfaceRule = sequence(
		condition(biome(Biomes.DESERT), block(Blocks.SAND)),
		condition(stoneDepthFloor(offset = 0, addSurfaceDepth = false, secondaryDepthRange = 0), block(Blocks.GRASS_BLOCK)),
		block(Blocks.STONE),
	)
}

// After: a surfaceRules { } scope, condition() takes a block lambda
noiseSettings("overworld") {
	surfaceRules {
		condition(biomes(Biomes.DESERT)) { block(Blocks.SAND) }
		condition(stoneDepth(Surface.FLOOR, addSurfaceDepth = false, secondaryDepthRange = 0)) { block(Blocks.GRASS_BLOCK) }
		block(Blocks.STONE)
	}
}
Kotlin
// Before: carvers split between air and liquid lists on the biome
biome("my_biome") {
	carvers(air = listOf(ConfiguredCarvers.CAVE), liquid = listOf(ConfiguredCarvers.CANYON))
}

// After: a configuredCarvers { } scope, and one flat carvers list on the biome
configuredCarvers {
	cave("my_cave") {
		probability = 0.15
		y = uniformHeightProvider(aboveBottom(8), absolute(180))
		replaceable(Blocks.STONE, Blocks.DIRT, Tags.Block.BASE_STONE_OVERWORLD)
	}
}
biome("my_biome") {
	carvers(ConfiguredCarvers.CANYON, ConfiguredCarvers.CAVE)
}
Kotlin
// Before: positional predicates, offset shared by the whole filter
configuredFeaturesBuilder.spike("test_spike", canPlaceOn = Solid, canReplace = Solid, state = blockStateStone())
blockPredicateFilter(allOf { matchingBlockTag(tag = Tags.Block.DIRT) })

// After: scoped blocks, offset moved inside each predicate
configuredFeaturesBuilder.spike("test_spike", state = blockStateStone()) {
	canPlaceOn { solid() }
	canReplace { solid() }
}
blockPredicateFilter { predicate { matchingBlockTag(Tags.Block.DIRT) { offset(0, -1, 0) } } }
Kotlin
// Before: template pool and processor list entries added through entry()/add()
templatePool("every_element") {
	fallback = TemplatePools.Village.Plains.TOWN_CENTERS
	entry(feature(PlacedFeatures.PILE_HAY), weight = 3, projection = Projection.TERRAIN_MATCHING)
}

// After: one flat builder method per element type, weight/projection as named params
templatePool("every_element") {
	fallback = TemplatePools.Village.Plains.TOWN_CENTERS
	feature(PlacedFeatures.PILE_HAY, weight = 3, projection = Projection.TERRAIN_MATCHING)
	single(Structures.EndCity.BRIDGE_GENTLE_STAIRS, ProcessorLists.HOUSING, weight = 2) {
		overrideLiquidSettings = LiquidSettings.IGNORE_WATERLOGGING
	}
}

processorList("every_processor") {
	blockRot(0.75, Blocks.STONE_BRICKS, Tags.Block.STAIRS)
	capped(6, Nop)
	gravity(HeightMap.OCEAN_FLOOR, offset = -1)
}
Kotlin

World presets keyed by dimension id

Dimensions are keyed by their id instead of their type, so two dimensions can share a type, and generator builders set generator themselves.

// Before: keyed by dimension type, generator assigned by hand, one type usable only once
worldPreset("my_preset") {
	dimension(DimensionTypes.OVERWORLD) {
		generator = noiseGenerator(NoiseSettings.OVERWORLD, multiNoise(BiomePresets.OVERWORLD))
	}
}
dp.noise("hills", firstOctave = -5, amplitudes = listOf(1.0, 0.5, 0.25))

// After: keyed by dimension id, the builder sets generator itself, amplitudes is variadic
worldPreset("my_preset") {
	dimension(Dimensions.OVERWORLD, DimensionTypes.OVERWORLD) {
		noiseGenerator(NoiseSettings.OVERWORLD, multiNoise(BiomePresets.OVERWORLD))
	}
	dimension(DimensionArgument("mining", "test"), DimensionTypes.OVERWORLD_CAVES) {
		noiseGenerator(NoiseSettings.CAVES, multiNoise(BiomePresets.OVERWORLD))
	}
}
dp.noise("cave/entrance") { firstOctave = -5; amplitudes(1.0, 0.5, 0.25) }

// Superflat settings get a layers { } builder, and structureOverrides takes structure set tags
flatLevelGeneratorPreset("tunnelers_dream", Items.STONE) {
	settings {
		layers { layer(Blocks.BEDROCK); layer(Blocks.STONE, height = 230); layer(Blocks.GRASS_BLOCK) }
		structureOverrides(StructureSetTagArgument("my_structure_sets", "test"))
	}
}
Kotlin

Sulfur cubes

// Before: a single explosionFuse field
sulfurCubeArchetype("regular", items = Tags.Item.SWORDS) { explosionFuse = 80 }

// After: structured explosion, contact damage and knockback, plus sound settings
sulfurCubeArchetype("regular", Tags.Item.SWORDS, horizontalKnockbackPower = 0.4f, verticalKnockbackPower = 0.2f) {
	contactDamage(amount = 3f, damageType = DamageTypes.GENERIC, attributeToSource = true)
	explosion(fuse = 80, power = 3, causesFire = true)
}
Kotlin

Migration notes

Every rename in this cycle, with the code to change on your side.

UUID becomes Uuid

The stable kotlin.uuid.Uuid is idiomatic, simpler, and multiplatform. If you only use the uuid() helpers, nothing changes.

// Before
UUID.fromString("6c0b9f1e-...")
UUID.randomUUID()

// After
Uuid.parse("6c0b9f1e-...")
Uuid.random()
Kotlin

item(...) becomes items(...) on item predicates

The builder takes several items and matches any of them, so the plural fits. Loot table entries keep their own item(...), which drops a single item.

// Before
matchTool { item(Items.DIAMOND_PICKAXE, Items.NETHERITE_PICKAXE) }

// After
matchTool { items(Items.DIAMOND_PICKAXE, Items.NETHERITE_PICKAXE) }
Kotlin

Sub-predicates take their vanilla name

Each one is named after the vanilla type it produces, so a name found in the wiki maps to the Kore one, and the global functions stop clashing with other builders of the same name. The loot context enum EntityType became EntityTarget to stop clashing with the EntityTypes registry.

// Before
effects { this[Effects.INVISIBILITY] = effect { amplifier = rangeOrInt(1) } }
equipment { mainHand = itemStack(Items.DIAMOND_SWORD) }
slots { this[WEAPON.MAINHAND] = itemStack(Items.DIAMOND_SWORD) }
location { block { blocks(Blocks.STONE) } }
scoreNumber("kills", EntityType.THIS)

// After
effects { this[Effects.INVISIBILITY] = mobEffectPredicate { amplifier = rangeOrInt(1) } }
equipment { mainHand = itemStackPredicate(Items.DIAMOND_SWORD) }
slots { this[WEAPON.MAINHAND] = itemStackPredicate(Items.DIAMOND_SWORD) }
location { block(Blocks.STONE) }
scoreNumber("kills", EntityTarget.THIS)
Kotlin

timeCheck requires its clock

Vanilla needs a clock to know which time to read, so it moved from a trailing nullable argument to the mandatory first one.

// Before
timeCheck(10f..20f, clock = WorldClocks.OVERWORLD)
timeCheck(0f..6000f, period = 24000, clock = WorldClocks.THE_END)

// After
timeCheck(WorldClocks.OVERWORLD, 10f..20f)
timeCheck(WorldClocks.THE_END, 0f..6000f, period = 24000)
Kotlin

valueCheck requires its range

A value_check without a range never matches anything, so the range is mandatory. An IntRange overload comes with it, since the game clamps both bounds to an integer anyway.

// Before
valueCheck(scoreNumber("kills", EntityType.THIS))

// After
valueCheck(scoreNumber("kills", EntityTarget.THIS), 1..10)
valueCheck(scoreNumber("kills", EntityTarget.THIS), intRange(0f, 10f))
Kotlin

Score holders are now a sealed ScoreProvider

Two nullable parameters let you pass both or neither and get invalid JSON, so the holder is a sealed type now: contextScore for a loot context entity, fixedScore for a name.

// Before
scoreNumber("kills", target = EntityType.THIS)
scoreNumber("kills", name = "Ayfri")

// After
scoreNumber("kills", contextScore(EntityTarget.THIS))
scoreNumber("kills", fixedScore("Ayfri"))
Kotlin

providersRange(...) becomes intRange(...)

Both built the same bound, so they are merged under intRange, which covers floats, providers, ClosedFloatingPointRange and IntRange.

// Before
limitCount(providersRange(min = constant(1f), max = constant(32f)))

// After
limitCount(intRange(min = constant(1f), max = constant(32f)))
Kotlin

Number providers only resolve inside their scopes

constant, uniform and the others now extend IntProviderScope/FloatProviderScope, so they only show up where a provider is accepted, and the int and float versions stop being ambiguous. weightedList gets a shorter syntax at the same time.

// Before
count(weightedList {
	add(weightedEntry(7, constant(1)))
	add(weightedEntry(3, constant(3)))
})

// After
count(weightedList {
	entry(7, constant(1))
	entry(3, constant(3))
})
count(weightedList(7 to constant(1), 3 to constant(3)))
Kotlin

HeightConstant becomes VerticalAnchor

Vertical anchors and height providers are scoped too, so they only appear where a height is expected.

// Before
heightRange(uniform(HeightConstant.aboveBottom(8), HeightConstant.belowTop(2)))

// After
heightRange(uniformHeightProvider(aboveBottom(8), belowTop(2)))
Kotlin

equippable takes a generated EquipmentAssets entry

The asset id was typed as ModelArgument, so any model name compiled. EquipmentAssets is generated from the vanilla list instead.

// Before
equippable(EquipmentSlot.HEAD, ModelArgument("iron"))

// After
equippable(EquipmentSlot.HEAD, EquipmentAssets.IRON)
Kotlin

Dripstone becomes speleothem

Vanilla renamed the features in 26.2, and they gained base_block, pointed_block and replaceable_blocks.

// Before
configuredFeature("cluster", dripstoneCluster(...))
configuredFeature("pointed", pointedDripstone(...))

// After
configuredFeatures {
	speleothemCluster("cluster") { /* baseBlock, pointedBlock, replaceableBlocks */ }
	speleothem("pointed") { /* ... */ }
}
Kotlin

Removed, with no replacement

weird_scaled_sampler and the noise_gradient surface rule are gone from vanilla, so they are gone from Kore. noise_threshold gained an optional 3D evaluation and covers most of what noise_gradient was used for.

New builders worth knowing

// team modify <team> color reset
modify("my_team") { colorReset() }

// scatter a placed feature around its origin
configuredFeaturesBuilder.randomPatch("flowers", PlacedFeatures.FLOWER_DEFAULT) {
	tries = 64
	xzSpread = 5
	ySpread = 2
}
Kotlin

Changelog

Documentation

  • docs(commands): Clarify and expand the command docs. 1d1e597
  • docs(components): Revise the components guide to update examples, clarify predicates, and link the component matchers table. 9d3cf51
  • docs(contributing): Update the architecture guide with GeneratedSealedSerializer usage and KSP-based serializer factory details. b5cf883
  • docs(generation): Add short KDoc to the generation module's key entry points. f8b527a
  • docs(home): Add community project links and the jumpr entry to the README list. e6b41aa 5aaf9c4
  • docs(oop): Improve the item, scoreboard, and team documentation. 708af24
  • docs(vfx-engine): Enhance the VfxEngine documentation with detailed explanations on shapes, coordinate spaces, and offsets. 035c1b9
  • docs(website): Update the guide content, clarify Kore usage and migration paths, add a version matrix to the Home page. 0af799b
  • docs(worldgen): Add a dedicated Carvers page and move the carver sections out of the Biomes page. d2f3cf1
  • docs(worldgen): Document the IntProviderScope/FloatProviderScope builder receivers on the Providers page, fix the stale providersRange/binomial snippets in Item Modifiers and Loot Tables. 6aec34b
  • docs(worldgen): Restructure the worldgen pages around a single end-to-end example, extract the shared providers to their own page, and condense the environment attribute reference into tables. 6aa1827
  • docs(worldgen): Rewrite the Noise & Terrain page as a full density function, noise router, and surface rule reference. 38558ae
  • docs(worldgen): Rewrite the Structures processor list and template pool sections with the scoped element builders. c403250 ba6c643

New Features

  • feat(arguments): Add toStringWithDecimal for consistent decimal point formatting, update the positional, rotational, and vector conversions. 03158e9
  • feat(bindings): Add the DatapackUpload API for exploring and importing datapack ZIPs in-memory, with cross-platform tests. 7dc0800
  • feat(bindings): Enhance parseReference to support dotted GitHub repo names. a3f00b4
  • feat(commands): Add team modify <team> color reset through colorReset. f6c6bc5
  • feat(datapack): Introduce folderName to decouple output folder names from namespaces, add tests for the folder, jar, and zip modes. 8497d8b
  • feat(enchantments): Add the geyser, geyser_base, geyser_plume, and geyser_poof particle options with unit tests. ccea6c1
  • feat(entity-predicates): Introduce type-specific EntitySubPredicate subclasses (CubeMob, FishingHook, Lightning, Player, Raider, Sheep) and an EntityTypeSpecificScope to group them. 987b370
  • feat(execute): Change run's block to Function.() -> Unit, allowing if/for control flow inside it. abc4a5c
  • feat(fabric): Add ResourceCondition with fabricLoadConditions, implement condition-based JSON generation. 10543f8
  • feat(generation): Add a DatapackFolderRegistry generator producing a datapack-folder-to-Argument-type map from the existing generator definitions. 75bf9a9
  • feat(generation): Add a pure-Kotlin ZipReader and Inflate for cross-platform ZIP handling, unify the unzip logic with commonUnzipToTempDir. 2cad91a
  • feat(generation): Generate the EnchantmentProviders and EquipmentAssets enums, retype equippable around EquipmentAssetArgument. c2c2bc5
  • feat(generation): Introduce platform-agnostic I/O with PlatformIO, OPFS browser support, and a pure-Kotlin ZipWriter, unifying file operations across JVM, JS, and browser. 05e7b6a
  • feat(helpers): Add a minimal in-house port of org.joml (Matrix4f, Matrix3f, AxisAngle4f, Quaternionf, Vector3f, JomlMath) for display transformation math. 0265cd6
  • feat(item-components): Add the SulfurCubeContentComponent, with tests and documentation. 8afcac3
  • feat(selector-arguments): Add fromString to parse selectors back from text, with deserialization logic and advanced selector support. 6feb45f
  • feat(sulfur-cube-archetype): Add the sulfur_cube_archetype data-driven registry with attribute modifiers and buoyancy. b2e9a3d
  • feat(sulfur-cube-archetype): Replace explosionFuse with structured explosion, contactDamage, and knockback powers, then add hit and push sound settings with pushSoundCooldown and pushSoundImpulseThreshold. 03233a1 42a9fbb df98bdf
  • feat(test-environments): Add the difficulty test environment with unit tests. 961bbe7
  • feat(vfx-engine): Add coordinate space support to drawShape, enhance VfxShape with positionType and origin. 2a5a916
  • feat(worldgen): Accept a block ID or list of IDs, in addition to a tag, for the geode, root system, vegetation patch, dimension type infiniburn, and protected blocks replaceable fields. 7349b97
  • feat(worldgen): Add the sequence and template configured feature types. 53eb47e
  • feat(worldgen): Add the weighted_random_selector configured feature, plus levelTestDistance and maxLevelDeviation on root_system. bf4163c f9fdad8
  • feat(worldgen): Add the interval_select density function and the matching_biomes block predicate, remove weird_scaled_sampler, make the multiface_growth block and the tree below_trunk_provider mandatory. af33acf
  • feat(worldgen): Add optional 3D evaluation to noise_threshold and remove the obsolete noise_gradient surface rule. d25fd01
  • feat(worldgen): Introduce IntProviderScope/FloatProviderScope as builder receivers across placed features, configured features, dimension types, enchantment providers, carvers, and processors, and add the random_patch configured feature. 779217c
  • feat(worldgen): Enhance the Lake configuration with the canPlaceFeature, canReplaceWithAirOrFluid, and canReplaceWithBarrier block predicates. dccef30
  • feat(worldgen): Rename the dripstone_cluster/pointed_dripstone configured features to speleothem_cluster/speleothem, add the base_block/pointed_block/replaceable_blocks fields, and add replaceable_blocks to large_dripstone. 9a56efe

Bug Fixes

  • fix(bindings): Fix the illegal interface property initializers and unsafe identifiers left in the Resources and Tags generators. 53d8836
  • fix(chat-components): Simplify the serialization logic for extra fields and enhance the JSON/NBT handling in chat components. 0aee14b 34d72bb 400f99f
  • fix(commands-execute): Correct the targetArg logic to handle UUIDArgument equality with a self-check, and optimize the selector argument handling. 59c6eca
  • fix(components): Add the missing saddle equipment slot. b5df734
  • fix(datapack): Set pack_format to an integer only and fix its default value. b613e04
  • fix(enchantments): Write the providers to enchantment_provider instead of trades, and allow any file name and sub-folder. 7d649e9
  • fix(helpers): Rewrite fromAxisAngle to use sin/cos trigonometric calculations instead of instantiating a Quaternionf. c25bcdf
  • fix(item-components): Change food's nutrition field from Float to Int, make use_cooldown's cooldown_group optional, and remove the invalid contact_cooldown_ticks field from kinetic_weapon. d47a492 2175192 1de41ea
  • fix(item-components): Rename attack_range's min_range/max_range to min_reach/max_reach, blocks_attacks's disable_sound to disabled_sound, and firework_explosion's has_flicker to has_twinkle. f6ef4da 26bf1b2 415971b
  • fix(item-components): Serialize the SulfurCubeContentComponent as an inlined item id instead of a nested object. 65db924
  • fix(item-predicates): Add support for partial and negated components, enhance clearPredicate, and simplify the setPartial and negate logic. 3e7804d
  • fix(pack): Fix the packFormat warning wrongly reported as outside the min_format/max_format range when it shares their major version. b458689
  • fix(predicates): Rename the mob effect ambiant field to ambient, and write the periodic_tick and type_specific/cube_mob sub-predicate keys vanilla expects. 9a20f9b f3b3204
  • fix(serializers): Serialize and deserialize half-open bounds in FloatRangeOrFloatJsonSerializer instead of throwing. 2e273bf
  • fix(worldgen): Fix the noise and spline density functions and the stone_depth surface type to match the vanilla JSON, make the noise settings tests exhaustive. d09d92f
  • fix(worldgen): Rename the misspelled biome spawner categories to ambient, axolotls, and waterAmbient, and add the missing misc one. 626e421 c4946a4
  • fix(worldgen): Replace the ocean ruin type field by biomeTemp, and default the jigsaw size to 1 instead of the out-of-range 0. 635cc66 0e9bd53
  • fix(worldgen): Return a ConfiguredStructureArgument from every configured structure builder so structure sets accept them. fab9d5c

Performance improvements

  • perf(arguments): Scope the Argument interface classpath scan to the arguments packages and parallelize the Class.forName lookups. 00bfcde
  • perf(datapack): Cache the jsonEncoder instead of rebuilding a Json config on every access. 7441a97
  • perf(item-components): Encode component values directly instead of round-tripping through a JsonElement/NbtTag tree, and skip the redundant encode-to-element pass in ComponentsScope.asJson/asNbt. de3a95e f69791c

Refactors

  • refactor(uuid)!: Replace java.util.UUID with kotlin.uuid.Uuid across modules, updating the related methods and constructors.
  • refactor(components): Move the item sub-predicates to components/matchers as DataComponentPredicate and EnchantmentPredicate, rename item(...) to items(...), and add the missing villager/variant matcher. 72b3a6b
  • refactor(density-functions): Add the densityFunctions builder with per-type block syntax, fix the snakeCase acronym and digit boundaries. dfe5c62
  • refactor(enchantments): Share the effect builders through scopes, fix the explode, play_sound, and crossbow_charging_sounds codecs, and complete the effect components. 9a2be54
  • refactor(predicates): Rename the sub-predicates to their vanilla *Predicate names, fix their serialization against vanilla-mcdoc, and require clock on timeCheck. 111e1a1
  • refactor(predicates): Split the score targets into a ScoreProvider sealed type, require ranges on valueCheck, and add the IntRange overload. 1674e14
  • refactor(trade-sets): Enhance TradeSet with new builder methods for trade amounts and sequences, with tests for empty and single trades. 892f75e
  • refactor(worldgen): Scope the configured carver builders to ConfiguredCarversScope, add the missing nether_cave type, fix the vanilla defaults and the flat biome carvers list. f68c443
  • refactor(worldgen): Scope the surface rule builders to SurfaceRulesScope, replace entry() with state/empty, and collapse the single-rule conditions. 1068a96
  • refactor(worldgen): Scope the processor list builders to ProcessorsScope, fix the blackstone_replace name and the vanilla defaults. 0ddc09c
  • refactor(worldgen): Scope the template pool builders to PoolEntriesScope and PoolElementsScope, fix the vanilla defaults, and add the legacySingle liquid settings. 87c932c
  • refactor(worldgen): Scope the block predicate, block state provider, and rule test builders, replace offset with a per-predicate offset { }, add unobstructed and targets { } on the ore-like features, and fix the noise_threshold_provider, randomized_int_state_provider, and tag_match naming. 43d05a9 cf5c3c8 872ab1c
  • refactor(worldgen): Rename HeightConstant to VerticalAnchor, scope the anchor and height provider builders, and document them with tests. e5ebca4
  • refactor(worldgen): Key the world preset dimensions by their id instead of their type, make every dimension generator builder set generator, remove the obsolete natural dimension type field, and add a layers { } builder for the superflat settings. e8ca92c 41c83f7 99f997e bed0900
  • refactor(worldgen): Replace the list-based amplitude and octave methods with a unified amplitudes(...). 2de880c
  • refactor(worldgen): Retype the structures builder around a StructuresScope, fix the mineshaft, shipwreck, spawn override, and generation step keys, and document every type with tests. 6a0795f

Full changelog: https://github.com/Ayfri/Kore/compare/v2.6.1-26.1..v2.13.1-26.2-rc-2

Minecraft 26.15

21 Jul 20263 months ago

2.8.0

MC 26.1.2Release

Big one this release: Kore was JVM-only until now. kore, oop, helpers and bindings are all Kotlin Multiplatform (JVM + JS, browser and Node.js), at the same coordinates. Full writeup here: Multiplatform Support.

kotlin {
	jvm()
	js { browser(); nodejs() }
}

// works on every target
val zipBytes: ByteArray = pack.generateZipBytes()

// JVM/Node only, real filesystem
val datapack = exploreDatapackZip(zipBytes, "uploaded_pack.zip")
Kotlin

That's powered by new pure-Kotlin ZipReader/ZipWriter + PlatformIO (OPFS in the browser), a hand-rolled codegen model replacing KotlinPoet in bindings, and KSP-generated serializers replacing reflection everywhere. Two dependencies gone as a result: org.joml (re-ported by hand, see below) and kotlin-reflect.

A few smaller additions too:

// folderName: decouple output folder from namespace
datapack {
	folderName("generated")
}

// run: if/for directly in the block
execute {
	run {
		if (condition) say("hi")
	}
}

// selectors: parse back from text
val selector = Selector.fromString("@e[limit=1,tag=!foo]")
Kotlin

Plus a minimal in-house org.joml port (Matrix4f, Matrix3f, AxisAngle4f, Quaternionf, Vector3f, JomlMath) for display transforms, one less dependency, and fabricLoadConditions/ResourceCondition for condition-based Fabric resources. Less libraries: faster and simplified Kore usage.

Documentation

  • docs(contributing): Update architecture guide with GeneratedSealedSerializer usage and KSP-based serializer factory details. b5cf883

New Features

  • feat(arguments): Add toStringWithDecimal for consistent decimal point formatting, update positional, rotational, and vector conversions. 03158e9
  • feat(bindings): Add DatapackUpload API for exploring and importing datapack ZIPs in-memory, implement cross-platform tests. 7dc0800
  • feat(bindings): Enhance parseReference to support dotted GitHub repo names, update tests to verify functionality. a3f00b4
  • feat(datapack): Introduce folderName to decouple output folder names from namespaces, add tests for folder, jar, and zip modes, and update documentation for creating datapacks. 8497d8b #246
  • feat(execute): Change run's block to Function.() -> Unit, allowing if/for control flow. abc4a5c #243
  • feat(fabric): Add ResourceCondition with fabricLoadConditions, implement condition-based JSON generation. 10543f8
  • feat(generation): Add DatapackFolderRegistry generator producing a datapack-folder-to-Argument-type map from existing generator definitions. 75bf9a9 #246
  • feat(generation): Add pure-Kotlin ZipReader, Inflate for cross-platform ZIP handling, unify unzip logic with commonUnzipToTempDir. 2cad91a
  • feat(generation): Introduce platform-agnostic I/O abstractions with PlatformIO, implement OPFS browser support, add ZipWriter for pure-Kotlin ZIP generation, and unify file operations across JVM, JS, and browser. 05e7b6a
  • feat(helpers): Add minimal port of org.joml classes including Matrix4f, Matrix3f, AxisAngle4f, Quaternionf, Vector3f, and JomlMath for display transformation math. 0265cd6
  • feat(selector-arguments): Add fromString to parse selector arguments, implement deserialization logic, enhance test cases, and support advanced selector parsing. 6feb45f

Bug Fixes

  • fix(datapack): Set pack_format to integer only and fix default value. b613e04 #245
  • fix(helpers): Rewrite fromAxisAngle to use trigonometric calculations with sin and cos, replacing Quaternionf instantiation, and adjust imports in Quaternion. c25bcdf

Full changelog: https://github.com/Ayfri/Kore/compare/v2.7.0-26.1.2..v2.8.0-26.1.2

2 Jul 20263 months ago

2.7.0

MC 26.1.2Release

This release updates Kore to Kotlin 2.4.0, which is great news because you don't need the -Xcontext-parameters compiler argument anymore ! I also migrated the UUIDArgument to use the new stable Uuid API from Kotlin instead of UUID from Java, this is because the API is more idiomatic to Kotlin and simpler and multiplatform.

If you're using the uuid() functions you probably don't need to change anything, else the migration is very easy:

UUID.fromString("...")
↓
Uuid.parse("...")
Kotlin
UUID.randomUUID()
↓
Uuid.random()
Kotlin

Documentation

  • docs(components): Revise components guide to update examples, clarify predicates, and link component matchers table. 9d3cf51
  • docs(generation): Add short KDoc to the generation module's key entry points. f8b527a

Refactors

  • refactor(uuid)!: Replace java.util.UUID with kotlin.uuid.Uuid across modules, update related methods and constructors accordingly.

Full changelog: https://github.com/Ayfri/Kore/compare/v2.6.2-26.1.2..v2.7.0-26.1.2

29 Jun 20263 months ago

2.6.1

MC 26.1Release
image

Welcome to Kore 26.1!

Kore 26.1 was a pretty long cycle.

It started with some groundwork on the late 1.21.11 side, then turned into a proper push for the new 26.1 data-driven systems. World clocks, timelines, villager trades, better time utilities, more worldgen coverage, and nicer OOP handles for displays and mannequins all landed here.

A lot of this cycle was also just polish, in the good way. There are plenty of docs, tests, serializer cleanups, and small API fixes in here because 26.1 added a lot of surface area, and I wanted Kore's DSL around it to feel nice instead of just technically complete.

What's new?

The big stuff this cycle was:

  • World Clocks and the expanded Time DSL let you create custom clocks, timelines, time markers, clock-aware predicates, and time.of(clock) command flows.
  • Villager Trades introduce fully data-driven villager_trade and trade_set generators, with item modifiers, predicates, and reusable trade pools.
  • Worldgen Features grew a lot during 26.1: more vanilla configured features, better block state providers, new height and number providers, and stronger test coverage for generated JSON.
  • Display Entities and Mannequins gained cleaner OOP entity handles, making it easier to summon, target, move, and manage generated entities from Kotlin.

A lot of the later releases were quieter, but they still mattered. Most of that work went into tightening serialization, filling API gaps, and expanding docs and test coverage for worldgen, predicates, commands, and helpers.

Code examples

Here are a few examples of what the biggest 26.1 additions look like in practice.

World clocks, timelines, and commands

val seasonClock = dataPack.worldClock("season")

dataPack.timeline("seasons", clock = seasonClock) {
	periodTicks = 96000

	timeMarker("spring", ticks = 0, showInCommands = true)
	timeMarker("summer", ticks = 24000, showInCommands = true)
	timeMarker("autumn", ticks = 48000, showInCommands = true)
	timeMarker("winter", ticks = 72000, showInCommands = true)
}

function("skip_to_winter") {
	time.of(seasonClock).set(timeMarker("winter", "my_mod"))
}
Kotlin

Villager trades and trade sets

This one defines a custom trade and groups it into a level-based trade set, which is exactly the kind of data-driven economy flow 26.1 made possible.

val wheatTrade = dataPack.villagerTrade("wheat_for_emerald") {
	wants(Items.WHEAT, count = 20)
	gives(Items.EMERALD)
	maxUses = constant(16f)
	xp = constant(1f)
}

dataPack.tradeSet(
	"custom_farmer_novice",
	trades = listOf(wheatTrade),
	amount = constant(1f),
) {
	allowDuplicates = false
}
Kotlin

Expanded worldgen DSL

Worldgen got a lot more expressive in 26.1, with richer configured features, state providers, and placement helpers.

val oakTreeCfg = tree {
	blobFoliagePlacer(radius = constant(2), offset = constant(0), height = 3)
	foliageProvider = simpleStateProvider(Blocks.OAK_LEAVES)
	straightTrunkPlacer(baseHeight = 5, heightRandA = 2, heightRandB = 0)
	trunkProvider = simpleStateProvider(Blocks.OAK_LOG)
	belowTrunkProvider = ruleBasedStateProvider {
		fallback = simpleStateProvider(Blocks.DIRT)
		rule {
			ifTrue { hasSturdyFace(direction = Direction.DOWN) }
			then(simpleStateProvider(Blocks.GRASS_BLOCK))
		}
	}
}

val oakTree = dataPack.configuredFeature("oak_tree", oakTreeCfg) {}

dataPack.placedFeature("oak_tree_placed", oakTree) {
	inSquare()
	count(constant(8))
	heightRange(trapezoidHeightProvider(minInclusive = 64, maxInclusive = 100, plateau = 12))
	biome()
}
Kotlin

OOP handles for generated entities

Helpers and OOP utilities also became easier to compose, especially when you want a generated display or mannequin to turn into a strongly-typed handle you can reuse later.

val display = blockDisplay {
	blockState(Blocks.STONE)
}.interpolable(vec3(0, 64, 0))

display.summon()

val entity = display.toEntity<BlockDisplayEntity>()

entity.addTag("intro_display")
entity.teleportTo(0, 65, 0)
Kotlin

Changelog

Documentation

  • docs(advanced): Extend Known_Issues.md with detailed limitations and workarounds for Kore. 51f7ab3
  • docs(ai): Update README and Home.md to include Kore-Skill AI skills pack link. 0cde2af
  • docs(bindings): Update Bindings.md with new setup steps and example improvements. d0028c5
  • docs(commands): Add KDoc to all commands. e5bf892
  • docs(commands): Fix wrong syntaxes in commands examples. 16ba50b
  • docs(concepts): Add Selectors.md with comprehensive overview on building Minecraft target selectors in Kore, including typed builders, filtering capabilities, and score-based conditions. 2d44932
  • docs(concepts): Add Time documentation for ticks, seconds, and days, usage examples, arithmetic, conversions, and command integration. 9b2c569
  • docs(contributing): Add Arguments.md and Cookbook.md for contributors. Introduction to Kore's argument system, practical datapack patterns, including setup functions, logic reuse, custom items, delayed actions, and more. 150a544 80bc008
  • docs(getting-started): Add link to "Learn X in Y Minutes - Kotlin" for a quick syntax refresher. 8b8750b
  • docs(getting-started): Expand Kotlin basics section, add explanations for val/var, functions, and extension functions, include quick learning resources links. 9ac611c
  • docs(guide): Revamp Getting_Started.md to provide a more comprehensive guide, emphasizing iterative development, modular project structure, and practical tips. ddbcb78
  • docs(guides): Add advanced migration guide from Datapacks to Kore. 5c22eba
  • docs(guides): Enhance configuration guide with detailed explanations. 8a3862f
  • docs(helpers): Update Display_Entities and Mannequins docs with OOP entity handles, code examples, and enhanced functionality descriptions. 48fac17
  • docs(markdown): Standardize links and hyphenation in documentation, fix inconsistent Markdown syntax, and improve clarity in examples and descriptions. c5df568
  • docs(nbt): Add complete documentation about NBTs. 5a7592d
  • docs(number-providers): Add KDoc to all number providers, update documentation. 8ff7ba5
  • docs(pages): Add copy button for markdown content and load sources. ec2d4c1 2ec7dcf
  • docs(villager-trades): Add Villager Trades documentation, update related pages with references to trade gating, item modifiers, and enchantments. 68f02d9
  • docs(world-clock): Add the World Clocks guide, update Timelines to reference clocks and time markers, improve examples, and align the docs with snapshot 26.1 changes. f3436b5
  • docs(worldgen): Add documentation for FloatProvider types with descriptions, examples, and usage scenarios in feature configuration. 2b1991e
  • docs(worldgen): Document IntProvider types with descriptions, examples, and usage scenarios in feature configuration. aeb9e5f
  • docs(worldgen): Expand Features.md with new vanilla feature types, no-config objects, modifiers, and height providers. Add examples, update descriptions, and fix typos. 676cc22

New Features

  • feat(arguments): Introduce MOB.INVENTORY, replacing the old PIGLIN and VILLAGER slots. aba3d82
  • feat(advancement): Add the player-interact-with-entity trigger. 69cd1be
  • feat(bindings): Add support for customizable HTTP request payload and headers, update related tests and documentation. eefe605
  • feat(bindings): Enhance the GitHub function with API key authentication details, add tests and docs. 00f7dcf
  • feat(chat-components): Add the fallback property to ObjectTextComponent and its subcomponents, update builders, tests, and docs. 30b7b80
  • feat(commands): Add the first swing command support with SwingHand and unit tests. e8bc54f
  • feat(commands): Add placeJigsaw overload with JigsawArgument, enhance placeTemplate with integrity and TemplateMirror, and improve KDoc for place functions. f885b8f
  • feat(commands): Expand /time with of subcommands for clocks, add pause, resume, new queries and setters, update docs and tests. 09fc73f
  • feat(commands): Expand swing with main-hand usage and targets support, update tests. f4ff4f4
  • feat(commands): Update locatePointOfInterest to use PointOfInterestTypeOrTagArgument, add KDoc comments to locate functions. 8a223fd 513a6d7 d4a906e
  • feat(data-driven): Add TradeSet and VillagerTrade generators with builder functions, integrate them into DataPack. 2d035ae c6f034b 94590e7
  • feat(datapack): Add path and iconPath utility functions, removing the need for the kotlinx.io library in simple projects. 8556f71
  • feat(entities): Add OOP entity handles for displays and mannequins, with selector-based targeting, UUID-based identity, and enhanced functionality. f22d89b
  • feat(entities): Add toEntity and entity factory methods for EntityType, update docs with usage examples, and extend tests to validate the new flow. 7e92bf3
  • feat(environment-attributes): Add ambientLightColor, blockLightTint, and nightVisionColor with tests and documentation. fa73f7a
  • feat(item-components): Add the AdditionalTradeCost component with tests and documentation. 79af872
  • feat(item-modifiers): Add includeAdditionalCostComponent to enchantRandomly and enchantWithLevels, update tests and documentation. c6f7022
  • feat(item-modifiers): Add setRandomDyes and setRandomPotion, update documentation and item modifier functionality. 55e6dae
  • feat(item-slot): Add the piglin item slot. 37a10b7
  • feat(nbt-utils): Add more builders for NBT lists. fbe3973
  • feat(oop): Add a more customizable ItemStack.summon. 91d4be2
  • feat(pig-sound-variants): Add the eatSound property to PigSoundVariant, update docs and tests. d96d2a4
  • feat(predicates): Add the environmentAttribute function and EnvironmentAttributeNumberProvider. 2e0c84e
  • feat(predicates): Add environmentAttributeCheck condition and overloads, update docs and tests. 654d184
  • feat(predicates): Add PlayerFoodPredicate with level and saturation, update tests and documentation. 09db797
  • feat(predicates): Add the clock parameter to TimeCheck, update overloads, and cover clock plus period combinations in tests. 7f1df0d
  • feat(predicates): Add the sum number provider, update documentation and tests. a4fc50e
  • feat(predicates): Add utility x, y, z setter functions to Position. 40995b2
  • feat(test-environments): Add the timelineAttributes environment, update docs and tests for timeline-driven mechanics. 5c6e0a6
  • feat(test-environments): Replace TimeOfDay with ClockTimeEnvironment, add a clock parameter, update tests and docs for clock-based time environments. 7b722ed
  • feat(time-command): Add the rate function to control day-night cycle speed, update tests and docs accordingly. 346ad90
  • feat(timelines): Add support for timeMarkers in timelines, introduce TimeMarkerArgument and TimelineMarker, update tests to cover marker usage and clock-aware flows. ea7bbef
  • feat(vec3): Enhance Vec3 and PosNumber with serialization support and docs. f68a73c
  • feat(website-styles): Add scrollMarginTop to the html element for better scrolling behavior. 7cfd313
  • feat(wolf-sound-variants): Add support for age-specific wolf sounds with adultSounds and babySounds, update tests and docs. c1c40b8
  • feat(worldclock): Add the WorldClock class and worldClock function, with tests for creation and registration. 77bd8a8
  • feat(worldgen): Add defaultClock to DimensionType, update tests and docs for WorldClock integration. 0af46d7
  • feat(worldgen): Add the endSpike factory function, update docs. b55db8d
  • feat(worldgen): Add extensive configuredFeature test coverage for many vanilla feature types, including bamboo, basaltColumns, dripstoneCluster, geode, and more. 53df549
  • feat(worldgen): Add FloatProvider factory functions with aliases for disambiguation, plus full unit test coverage for all supported float provider types. a1ea226
  • feat(worldgen): Add TrapezoidIntProvider and the trapezoid factory function, update functions.kt ordering. 16dab69

Bug Fixes

  • fix(advancement): Add the missing from AdvancementRoute, improve KDoc. bf07d93
  • fix(bindings): Correct the cache directory path in getCacheDir for consistency. 48bde8d
  • fix(bossbar): Add the missing setName overload with a text component and improve KDoc. 15b8767
  • fix(commands): Add the missing entity literal to teleport overloads, improve KDoc. 318f75e
  • fix(commands): Add the missing fill options for the fill command. c76866e
  • fix(commands): Add the missing set sub-literal for style in waypoint modify, refine KDoc for WaypointModify and related functions. c0a7fa2
  • fix(commands): Fix many clone grammar issues, add missing modes and sub-literals, improve KDoc. 9ed7482
  • fix(commands): Replace sequenceId with RandomSequenceArgument, improve random command KDoc. 5eb7557
  • fix(components): Replace InlinableList with List in ProvidesBannerPatterns, add PatternListSerializer, and update providesBannerPatterns helpers. 3515467
  • fix(data): Add missing support for string-based data commands, including append, insert, merge, and prepend operations. e041065
  • fix(docs): Update test commands in contributing documentation for consistency. 32feda0
  • fix(helpers): Fix the double namespace issue, broken self-recursion, and max-hit dedup in raycast. 933743b
  • fix(item): Correct the argument order in toItemArgument. 669152c
  • fix(playsound): Replace SoundArgument with SoundEventArgument in playSound. 4ae24e5
  • fix(stopwatch): Update the scale parameter to use a float type. 84edfb0
  • fix(time): Update Time.toString() to use toStringTruncatedIfRound, extend TitleCommand tests. 5b7969b
  • fix(vec): Fix the double truncation logic, add more tests, and repair the raycast test. b3e3618
  • fix(worldgen): Add the randomSelector factory function and DSL, update docs. 25114cc
  • fix(worldgen): Simplify Features serialization logic, replace InlinableListSerializer with ListSerializer, and preserve positional order with empty lists. ebde9c9

Refactors

  • refactor(item-components): Update components to support multiple IDs or tags for providesBannerPatterns, blocksAttacks, and damageResistant. 945596b
  • refactor(item-modifiers): Enhance setInstrument to support a single ID, a tag, or multiple IDs and tags, update related docs and tests. d3d82af
  • refactor(number-providers): Remove the custom serializer from ScoreTargetNumberProvider, simplify the implementation. e7d0d5a
  • refactor(worldgen): Add DSL improvements for RuleBasedBlockStateProvider, enhance rule configurability, update related tests and docs. 7af02b8
  • refactor(worldgen): Enhance the AlterGround tree decorator DSL, add builder block support, update tests and usage. c87b7e3
  • refactor(worldgen): Remove Flower, NoBonemealFlower, and RandomPatch configurations, update documentation to reflect the change. f16ae73
  • refactor(worldgen): Rename RuleBasedBlockStateProvider to RuleBasedStateProvider, update usages, tests, and docs accordingly. aef0afb
  • refactor(worldgen): Replace RuleBasedBlockStateProvider with BlockStateProvider across tree configurations, update the relevant docs and test cases. fa1f987

Full changelog: https://github.com/Ayfri/Kore/compare/v2.0.2-1.21.11..v2.6.1-26.1-rc-3

Minecraft 1.2126

29 May 20265 months ago

2.0.3

MC 1.21.11Release

Another small release with many improvements to the documentation, a few small fixes, a missing advancement trigger, and improvements to NBTs with even its own documentation page.

Documentation

  • docs(advanced): Extend Known_Issues.md with detailed limitations and workarounds for Kore. 51f7ab3
  • docs(ai): Update README and Home.md to include Kore-Skill AI skills pack link. 0cde2af
  • docs(getting-started): Add link to "Learn X in Y Minutes - Kotlin" for quick syntax refresher. 8b8750b
  • docs(getting-started): Expand Kotlin basics section, add explanations for val/var, functions, and extension functions, include quick learning resources links. 9ac611c
  • docs(guide): Revamp Getting_Started.md to provide a more comprehensive guide, emphasizing iterative development, modular project structure, and practical tips. ddbcb78
  • docs(guides): Add advanced migration guide from Datapacks to Kore. 5c22eba
  • docs(guides): Enhance configuration guide with detailed explanations. 8a3862f
  • docs(nbt): Add complete documentation about NBTs. 5a7592d
  • docs(pages): Add copy button for markdown content and load sources. ec2d4c1 2ec7dcf

New Features

  • feat(advancement): Add player interact with entity trigger 69cd1be
  • feat(nbt-utils): Add more builders for Nbt Lists. fbe3973
  • feat(oop): Add a more customizable ItemStack.summon. 91d4be2
  • feat(vec3): Enhance Vec3 and PosNumber with serialization support and docs. f68a73c

Bug Fixes

  • fix(data): Add missing data ... string commands support, append, insert, merge, and prepend operations. e041065

Refactors

Full changelog: https://github.com/Ayfri/Kore/compare/v2.0.2-1.21.11..v2.0.3-1.21.11

21 Apr 20266 months ago

2.0.2

MC 1.21.11Release

Small but big release, adding a lot of missing KDoc on commands, new documentation for Selectors, Arguments Internals for contributors and a Cookbook with common patterns you would want to know.

I've also fixed many small issues with rarely used commands. Point Of Interest enum generation and argument support for locate poi command, new way to configure Bindings Github API Key and url parameters.

Documentation

  • docs(bindings): Update Bindings.md with new setup steps and example improvements. d0028c5
  • docs(commands): Add KDoc to all commands. e5bf892
  • docs(commands): Fix wrong syntaxes in commands examples. 16ba50b
  • docs(concepts): Add Selectors.md with comprehensive overview on building Minecraft target selectors in Kore, including typed builders, filtering capabilities, and score-based conditions. 2d44932
  • docs(contributing): Add Arguments.md and Cookbook.md for contributors. Introduction to Kore's argument system, practical datapack patterns, including setup functions, logic reuse, custom items, delayed actions, and more. 150a544 80bc008

New Features

  • feat(bindings): Add support for customizable HTTP request payload and headers, update related tests and documentation. eefe605
  • feat(bindings): Enhance GitHub function with API key authentication details, add tests and docs. 00f7dcf
  • feat(commands): Add placeJigsaw overload with JigsawArgument, enhance placeTemplate with integrity and TemplateMirror, and improve KDoc for place functions. f885b8f
  • feat(commands): Update locatePointOfInterest to use PointOfInterestTypeOrTagArgument, add KDoc comments to locate functions. 8a223fd 513a6d7 d4a906e
  • feat(predicates): Add utility x, y, z setter functions to Position. 40995b2

Bug Fixes

  • fix(advancement): Add missing from AdvancementRoute, improve KDoc. bf07d93
  • fix(bindings): Correct cache directory path in getCacheDir function for consistency. 48bde8d
  • fix(bossbar): Add missing setName with text component and improve KDoc. 15b8767
  • fix(commands): Add set sub-literal for style in waypoint modify, refine KDoc for WaypointModify and related functions. c0a7fa2
  • fix(commands): Add missing entity literal to teleport overloads, improve KDoc. 318f75e
  • fix(commands): Add missing fill options for fill command. c76866e
  • fix(commands): Fix many clone command grammar issues, add missing modes and sub-literals, improve KDoc. 9ed7482
  • fix(commands): Replace sequenceId with RandomSequenceArgument, improve random command KDoc. 5eb7557
  • fix(docs): Update test commands in contributing documentation for consistency. 32feda0
  • fix(item): Correct argument order in toItemArgument method. 669152c #216
  • fix(playsound): Replace SoundArgument with SoundEventArgument in playSound command. 4ae24e5
  • fix(stopwatch): Update scale parameter to use float type. 84edfb0

Full changelog: https://github.com/Ayfri/Kore/compare/v2.0.1-1.21.11..v2.0.2-1.21.11

16 Apr 20266 months ago

2.0.1

MC 1.21.11Release

Small fix to execute if block and a lot of new documentation on how to contribute to Kore!

Documentation

  • docs(commands): Add KDoc to all execute and execute condition functions. 6773147
  • docs(contributing): Add comprehensive contributor guides on architecture, workflow, CI/CD, and generator creation. 50d926c
  • docs(contributing): Revise guidelines for contribution, link to detailed docs for architecture, workflow, and CI/CD, and update README and website with clearer contribution instructions. 1fbb46a
  • docs(home): Fix error in example code. 8ea2d2e

Bug Fixes

  • fix(execute): Add missing execute if block with BlockTag argument. 993bf55

Full changelog: https://github.com/Ayfri/Kore/compare/v2.0.0-1.21.11..v2.0.1-1.21.11

2 Apr 20266 months ago

2.0.0

MC 1.21.11Release
kore-2 0-banner

Welcome to Kore 2.0!

Kore 2.0 is here! This release contains so many changes, improvements, and new features that it deserved a major version bump. From a completely revamped build system to powerful new OOP utilities and helpers, this is the biggest update Kore has ever seen.

What's new?

The new Helpers module provides a rich set of utilities for common datapack patterns:

  • Math engine - vector math, area utilities, and floating-point formatting helpers for Vec2, Vec3, Position, and Rotation.
  • Raycasts - easily create block and entity raycasts with configurable step size, max distance, and hit callbacks.
  • State delegates - Kotlin property delegates backed by scoreboards.
  • Text utilities - selectors, text components, and formatting helpers.
  • MiniMessageRenderer, MarkdownRenderer, and ANSIRenderer - advanced text formatting renderers.
  • VFX & Particles - high-level particle helpers for visual effects.

Also, the prior Helpers have been moved to the helpers module, such as Display Entities, Inventory Manager, Mannequins, Scheduler, and ScoreboardManager. See also Scoreboard Math.

The OOP module brings object-oriented abstractions on top of Minecraft commands:

  • Boss Bars - create and manage boss bars with team integration.
  • Entity management - EntityCommands for fluent entity manipulation.
  • Events - event-driven architecture for datapack logic.
  • Game State Machine - GameState and GameStateManager for managing game phases and transitions.
  • Spawners - configurable entity spawner utilities.
  • Timers & Cooldowns - schedule delayed or repeating actions with Timer and Cooldown APIs.

Code examples

Here are a few examples of what you can build with the biggest additions in Kore 2.0.

Helpers

This first example combines the math helpers with a raycast to measure a path and react to blocks or entities hit along the way.

val origin = pos(0, 64, 0)
val target = pos(12.75, 65.0, -3.5)
val distance = origin.distanceTo(target)

function("helpers_demo") {
	comment("Formatted distance: ${distance.toStringTruncatedIfRound()}")

	raycast(
		from = origin,
		direction = rotation(0f, 0f),
		maxDistance = 32.0,
		step = 0.25,
		onHitBlock = ::hitBlock,
		onHitEntity = ::hitEntity,
	)
}
Kotlin

And this one uses the particle helpers to turn an impact point into a small visual burst.

function("helpers_particles_demo") {
	val impact = pos(4.5, 65.0, -2.5)

	particle(
		particle = flame(),
		pos = impact,
		delta = vec3(0.15, 0.35, 0.15),
		speed = 0.02f,
		count = 12,
	)
}
Kotlin

This one shows how state delegates let you read and write scoreboard-backed values like regular Kotlin properties.

class GameContext {
	var score by score("game.score")
	var phase by score("game.phase")
}

val context = GameContext()

function("state_delegate_demo") {
	context.score += 10
	context.phase = 2
	comment("Score: ${context.score} | Phase: ${context.phase}")

	runIf(context.phase eq 2) {
		say("Phase 2 is over!")
	}
}
Kotlin

OOP

Here, a boss bar and a timer are wired together so players see the bar appear and initialize automatically when the intro starts.

val bossBar = BossBar("game:boss") {
	name = text("Final Boss")
	color = BossBarColor.PURPLE
	max = 100
}

val introTimer = Timer("game:intro", 100) {
	bossBar.players += allPlayers()
	bossBar.value = 100
}
Kotlin

This last example shows the event system forwarding a player join into the current game state, which keeps phase-specific logic nicely encapsulated.

val gameStateManager = GameStateManager(
	initialState = LobbyState(),
)

events.listen<PlayerJoinEvent> {
	gameStateManager.currentState.onPlayerJoin(player)
}
Kotlin

And here a spawner is paired with a cooldown to keep waves under control without scattering timing logic everywhere.

val waveCooldown = Cooldown("game:next_wave", 200)

val arenaSpawner = Spawner("game:arena") {
	spawnEntity = EntityTypes.ZOMBIE
	position = pos(0, 64, 0)
}

events.listen<TickEvent> {
	if (waveCooldown.isFinished) {
		arenaSpawner.spawn()
		waveCooldown.reset()
	}
}
Kotlin

Changelog

CI/CD

  • Add ci.yml workflow for automated tests. 2720e85
  • Add publish-snapshot.yml workflow for snapshot builds, update docs with snapshot setup instructions, and enhance build logic for snapshot versioning. b93e1df

Documentation

  • Update bindings documentation for namespace remapping and normalization. 5c066da - @e-psi-lon
  • Add scoreboard comparison examples for equalTo, notEqualTo, and related helpers. Extend documentation with Kotlin DSL mappings to generated commands. a516ef1
  • Add new documentation for helpers module (renderers, raycasts, math, particles, state delegates). 941fa47
  • Enhance Helpers and OOP documentation with new workflows, API examples, expanded Events, Display Entities, Raycasts, and scheduling sections. e6d986d
  • Update module descriptions, installation guides, and examples for bindings, helpers, and oop modules. 4c59c0b
  • Add OOP documentation for cooldowns, timers, game state machine, boss bars, events, entities, and spawners. 761d7ec 89bb489 33747c3

New Features

  • State: Add score-based comparison functions, runIf, runWhile, and repeatScore helpers. Enhance ScoreboardDelegate with asExecuteScore and scoreboardEntity integration. fd63024
  • State: Replace repeatScore with repeat, update iteration handling, enhance documentation, and adjust tests and examples. ce4a0ef
  • Bindings: Add support for per-namespace renaming. e9ded19 - @e-psi-lon
  • Bindings: Use XDG-compliant caching and prefer Path over File. 67e8f76 - @e-psi-lon
  • Maths: Add utility functions for truncation and formatting in Position, Rotation, Time, Vec2, and Vec3, improve toString methods and type-specific property access. fb0be06
  • Maths: Add delegate-based math helpers, improve trigonometric functions, enhance sqrt initialization, and update tests and documentation. c16b0e79
  • OOP: Add OOP wrappers for entity management, game state transitions, timers, spawners, and boss bars. d677d20 a8b3ba9 46f9de7

Bug Fixes

  • Bindings: Normalize namespace object name. a1b167a - @e-psi-lon
  • Commands: Add missing literal("under") argument to spreadPlayers command. c7cdcfa
  • Arguments: Fix unintended cast of Double coordinates to Int (e.g. 0.0 → 0), replace str with toStringTruncatedIfRound for correct entity positioning. c28b4ba 08a37ef - #213
  • Files: Fix createTempDirectory actually not creating the temporary directory, add more utilities to Path, and update docs and tests. 0c95069

Refactors

  • Arguments: Add Argument parsing and deserialization logic, enhance BlockArgument serializer, and introduce proxy creation for arguments. 6353257 bedbedc
  • Bindings: Add @Suppress("DEPRECATION") for deprecated properties, update code generators to use CodeBlock for pack metadata, remove infix remapping function. 449b021 b6c500a c9c5f78 - @e-psi-lon
  • Bindings: Use native cache directory for macOS and Windows. a68df12 - @e-psi-lon
  • Build: Remove buildSrc, migrate build logic to build-logic directory, introduce kotlin-dsl plugin, define version catalogs, configure repositories, and add kotest-conventions for shared test configuration. f0aab38 601b748 d30d43f 788d574
  • Core: Remove unnecessary @OptIn annotations, fix typos, improve validation for path commonality check. 4a44232
  • Generation: Add merging logic for load.json/tick.json tags, improve path normalization, fix duplicate archive entries, and simplify mod function parameters. 7d938be 865947d
  • Helpers & OOP: Migrate helpers from oop to dedicated helpers module, add Area utilities, enhance GameState/GameStateManager, improve entities, timers, teams, and standardize indentation to tabs. ace2f01 2efe908 53cef64 fd2326d
  • Scoreboard: Replace fn.data/fn.scoreboard with direct calls, update copyDataFrom/copyTo logic. b948855
  • Serialization: Improve deserialization logic, simplify serializers by leveraging EnumStringSerializer, enhance NBT/JSON compatibility. 1785d7a 20677eb
  • Utils: Simplify dateFormats calculations, optimize imports in MarkdownRenderer, simplify parentElement type usage. 3c168b9

Thanks to @e-psi-lon for his contributions!

Full changelog: https://github.com/Ayfri/Kore/compare/v1.42.1-1.21.11..v2.0.0-1.21.11

20 Feb 20268 months ago

1.42.1

MC 1.21.11Release

Small release to fix the default datapacks containing features field, also simplify the usage of pack formats and add more KDoc. I've also revamped a bit the tool I use to generate changelogs.

Documentation

  • docs(datapack): Update Creating A Datapack guide, improve minFormat/maxFormat examples, add legacy format handling and overlays DSL usage documentation. 79a34d7

Bug Fixes

  • fix(datapack): Make features optional. 13d9bd8

Refactors

  • refactor(colors): Add ColorSerializer deserialization for hex and named colors. 32f7e7a
  • refactor(pack): Update pack.mcmeta handling, add DSL for overlays, improve serialization for legacy fields, and clarify deprecation warnings. fbf7e5d
  • refactor(worldgen): Simplify Features serialization logic, add InlinableListSerializer, optimize toList and fromList conversion methods. b3c5d96

Full changelog: https://github.com/Ayfri/Kore/compare/v1.42.0-1.21.11..v1.42.1-1.21.11

15 Feb 20268 months ago

1.42.0

MC 1.21.11Release

A release to fix many small issues with advancements/item-modifiers/loot-tables/predicates/structures/test-instances, also some simplifications of serializers. It contains some small breaking changes so that's why the version bump.

Changelog

  • feat(maths): Add toArray and fromArray conversion for Vec3f, add deserialization support. 97a589c
  • feat(worldgen-structures): Add Terrain Adaptation and Pool Aliases documentation, enhance pool alias logic with weighted entries in tests. 6309c34
  • fix(advancements): Rename AvoidVibrations to AvoidVibration. 7c09253
  • fix(docs): Update Advancements.md and Triggers.md, add brewedPotion. Enhance Item_Modifiers.md with new examples, correct inconsistencies. 5626439
  • fix(item-modifiers): Add @Serializable to SetBookCover. b9a2cc4
  • fix(item-modifiers): Fix serialization of ApplyBonus item modifier. e3a867f
  • fix(item-modifiers): Remove UUIDArgument, add id property in AttributeModifier. 3d51818
  • fix(item-modifiers): Rename potion to id in SetPotion. dff1c54
  • fix(item-modifiers): Replace nbt with tag in SetCustomData and write as inline nbt, add helper to setBannerPattern. c820f1f
  • fix(loot-tables): Rename name to value in LootTable. 58b6d3e
  • fix(predicates): Add Light class to replace light field in Location. 64cdfa4
  • fix(predicates): Rename Enchantment int provider to EnchantmentLevel, update related functions. 6289eae
  • fix(predicates): Rename EntityScore to EntityScores. f46733a
  • fix(predicates): Replace Block with Location in steppingOn. 784e0d3
  • fix(predicates): Set default value of entity in EntityProperties to EntityType.THIS. 76d8717
  • fix(test-instances): Replace FunctionArgument with String for function references, align logic and documentation with new GameTest framework. 7f3514a
  • fix(test-instances): Replace Function with FunctionArgument, remove FunctionDSLBuilder. 41fda93
  • fix(worldgen-structures): Update pool alias logic, introduce weighted entries. 309b9fe
  • refactor(advancements): Replace criteria serialization logic with InlineSerializer, adjust trigger classes to remove name property. 82f6727
  • refactor(advancements): Set default lambda value for recipeUnlocked and recipeCrafted criteria. 4eb7e7f
  • refactor(item-modifiers): Adjust Source enum values, rename parameters in copyCustomData, add helper methods for MutableList<CopyNbtOperation>. 11f9481
  • refactor(predicates): Simplify Fluid sub predicate usage. a4657b7

Full changelog: https://github.com/Ayfri/Kore/compare/v1.41.3-1.21.11..v1.42.0-1.21.11

13 Feb 20268 months ago

1.41.2

MC 1.21.11Release

Small fixes and improved predicates/pack usages.

Changelog

  • feat(pack): Add supportedFormats DSL, implement range and min-max validation, and add corresponding tests. 15d08f0
  • feat(predicates): Add matchTool function with ItemArgument support, enable multi-item condition handling. 60363c2
  • feat(predicates): Extend enchantments to support EnchantmentOrTagArgument with optional levels. 0ba6dd5
  • feat(utils): Add extractBaseMinecraftVersion, implement compareMinecraftVersions, update version filtering logic. 46be380
  • fix(loot-tables): Fix alternatives being mis-spelled and simplify usage. 177b236

Full changelog: https://github.com/Ayfri/Kore/compare/v1.41.1-1.21.11..v1.41.2-1.21.11

11 Feb 20268 months ago

1.41.1

MC 1.21.11Release

Massive update covering the snapshot cycle. Major additions to Worldgen, Environment control, and Combat components. Also a complete revamp of the documentation pages/architecture and to the updates page.

Changelog

Worldgen & Environment

  • feat(timelines): Introduced the Timelines System for data-driven environment animations (keyframes, easing).
  • feat(environment): Added fine-grained control for cloudColor, fogStart/End, waterFog, skybox, and CardinalLight.
  • feat(worldgen): Added BlendToGray modifier and Activity registry generator.

Combat & Components

  • feat(components): Added Weapon Components: KineticWeapon, PiercingWeapon, and DamageType.
  • feat(components): Added AttackRangeComponent with max/minCreativeReach.
  • feat(components): Added interactVibrations, minimumAttackCharge, and swingAnimation.

Datapack Utilities

  • feat(commands): Added worldborder (add/set/warning) and stopwatch commands.
  • feat(functions): Enhance addLine to support multiline strings, add test cases. 9775e08
  • feat(loot-tables): Added Slots entries (contents, empty, filtered, group, limit-slots) and fixed dynamic names.
  • feat(predicates): Added matchTool (multi-item support), isFallFlying, and isInWater.
  • feat(enchantments): Added ApplyImpulse, postPiercingAttack, and applyExhaustion.

Core & Docs

  • docs: Massive documentation overhaul (Worldgen, Tags, Trims, variants) + llms.txt support.
  • refactor: Migrated to Vanniktech Maven Publish (lighter & faster builds).

Full changelog: https://github.com/Ayfri/Kore/compare/v1.37.0-1.21.10..v1.41.1-1.21.11

14 Nov 202511 months ago

1.33.2

MC 1.21.8Release

Somes fixes, update to KNbt, new documentation and missing interfaces/generated things. Also, I'm currently working on something bigger and very interesting for Kore!

Changelog

  • chore(dependencies): Update knbt version from 0.11.8 to 0.11.9. c01183c
  • docs(macro): Add example for TeleportMacros and clarify limitations. 387be86
  • docs(publishing): Add guide for publishing datapacks using GitHub Actions. 98d7e5e
  • feat(generation): Add missing worldgen tags interfaces parents. 1a0e39e feat(generation): Add painting_asset to additional arguments and update tagsParents for PaintingAssetArgument. d095f93
  • feat(tags): Add missing common tags functions. d597df3
  • fix(advancements): Change background type to ModelArgument in AdvancementDisplay. c76b6b1
  • fix(execute): Fix execute if items syntax missing source literal name. 0202e87 #175
  • fix(generation): Move DEFAULT_DATAPACK_FORMAT to DataPack.Companion for easier use. 7a9c0ad
  • fix(painting): Change assetId type to PaintingAssetArgument in PaintingVariant. e3aff11, 966a085

Full changelog: https://github.com/Ayfri/Kore/compare/v1.33.1-1.21.8..v1.33.2-1.21.8

18 Sept 2025last year

1.33.1

MC 1.21.6Release

The big new "small" release is finally out! I took a long time because life is life, and you can get pretty busy at some times, but now Kore is back and updating quickly!

See the new 1.21.6 changes from Minecraft themselves: https://www.minecraft.net/en-us/article/minecraft-java-edition-1-21-6

Changelog

  • No changes were required since 1.21.6-rc1.

Full changelog: https://github.com/Ayfri/Kore/compare/v1.28.0-1.21.5..v1.33.1-1.21.6

12 Jan 2025last year

1.24.0

MC 1.21.4Release

Small release containing one bug fix! But I also updated Kore to 2.1.0, this changes the process of creating projects because you have to ignore one warning, sadly that's the best way I found for the current state of Kore. We're waiting on the context parameters feature to release to remove these flags, but currently the KEEP is still in construction.

You'll now have to add this flag to freeCompilerArgs list : "-Xsuppress-warning=CONTEXT_RECEIVERS_DEPRECATED" Example

kotlin {
	compilerOptions {
		freeCompilerArgs = listOf("-Xcontext-receivers", "-Xsuppress-warning=CONTEXT_RECEIVERS_DEPRECATED")
	}
}
Kotlin

Note that I've also updated Kore-Template.

Changelog

  • chore(build): Update compiler arguments for context receivers. 192f9c1
  • chore(dependencies): Update jetbrains-compose to version 1.7.3, update kobweb to version 0.20.0, and upgrade kotlin.version to 2.1.0. 18f75fb a33baf6
  • fix(scoreboard): Update asString method to use camelCase, add tests for some scoreboard criterion. #135 c6ed581
  • feat(string-utils): Add camelCase function to convert strings to camel case. f033e3b

Full changelog: https://github.com/Ayfri/Kore/compare/v1.23.0-1.21.4..v1.24.0-1.21.4

11 Nov 2024last year

1.17.0

MC 1.21.1Release

Another release with a big new feature : jar file generation. You can now create datapacks that can be used as mods for fabric, forge, neoforge and quilt mod-loaders ! Check out the documentation on this new feature here : https://github.com/Ayfri/Kore/wiki/creating-a-datapack#jar-generation The next release should be focused on updating Kore to 1.21.2 👌

Changelog

  • feat(creating-datapacks): Add NeoForge neoforge.mods.toml generation. f1f21e1 5f7f90c
  • feat(creating-datapacks): Add Quilt quild.mod.json generation. 44b75a
  • feat(creating-datapacks): Add forge mods.toml generation. 796a595
  • feat(creating-datapacks): Add jar generation and fabric mod generation. 3f60647
  • feat(generators): Generate minecraft version. c75f6cc
  • fix(neoforge): Fix NeoForge dependency type value should be lowercase.
  • refactor(datapacks): Streamline datapack generation from different mode into one unique, fix tags not merging when generating a zip, simplify generation. 22eb17b

Full changelog: https://github.com/Ayfri/Kore/compare/v1.16.0-1.21.1..v1.17.0-1.21.1

30 Oct 2024last year

1.16.0

MC 1.21.1Release

This release introduces a big new feature very cool for datapack developers: Being able to merge datapacks together, even with external datapacks or zip files. Check out the documentation on this new feature here. Let me know if this feature has any bugs or missing features!

Changelog

  • feat(chat-components): Introduce deserialization of chat components for Json. f105bd4
  • feat(datapacks): Add generations options, add merging with other packs option, add tests. d01296d
  • feat(pack-mcmeta): Introduce deserialization of SupportedFormats, add useful functions for comparing versions, add toString. 39d53e3
  • feat(tags): Introduce deserialization of Tags. 33a5b51

Full changelog: https://github.com/Ayfri/Kore/compare/v1.15.1-1.21.1..v1.16.0-1.21.1

16 Sept 20242 years ago

1.15.1

MC 1.21.1Release

Fixes a bug related to tag generation folder when setting the tag of a function using the setTag function, also updates unit tests about functions generation for checking if all files are correctly generated and are at the correct location.

[!IMPORTANT] I will in a future release rename the setTag function to addToTag because a function in Minecraft can be linked to multiple tags.

Changelog

  • fix(functions): Fix generated tag folder for setTag method of functions, update tests for functions generation files locations. #102 0efd2da

Full changelog: https://github.com/Ayfri/Kore/compare/v1.15.0-1.21.1..v1.15.1-1.21.1

Minecraft 1.205

22 Sept 20233 years ago

1.0.0

Kore Library v1.0.0 Released! 🎉

I'm excited to announce the first stable release of the Kore library! After months of development and testing, Kore v1.0.0 is now available.

Get started now with the documentation and the example.

Your feedback and contributions are welcome! Feel free to open issues or pull requests on the GitHub repository.

Happy datapacking! ⛏️