diff --git a/.changeset/bubble-anchor.md b/.changeset/bubble-anchor.md
deleted file mode 100644
index 0b2b7264..00000000
--- a/.changeset/bubble-anchor.md
+++ /dev/null
@@ -1,11 +0,0 @@
----
-type: patch
----
-
-Speech and thought bubbles hang off the sprite's hitbox.
-
-They were placed from the size of the costume, which is usually a canvas bigger
-than what is painted on it, so the bubble floated up and to the right of its
-sprite with its tail pointing at nothing. It now sits on the top right corner of
-the hitbox. For the built-in slime that moves it 14 pixels left and 72 down, onto
-its shoulder.
diff --git a/.changeset/builtin-names.md b/.changeset/builtin-names.md
deleted file mode 100644
index 66bb667b..00000000
--- a/.changeset/builtin-names.md
+++ /dev/null
@@ -1,10 +0,0 @@
----
-type: minor
----
-
-A built-in sprite name works everywhere a picture is named.
-
-`new Sprite("player", "slimeGreen")` threw `Could not load image: slimeGreen`:
-the constructor took a path where `addCostume()` took either. It now takes
-either, as do `Stage.setCursor`, `Window.useSplashLogo` and
-`Sprite.addCostumes`. A string with a file extension is still a path.
diff --git a/.changeset/change-position.md b/.changeset/change-position.md
deleted file mode 100644
index f54c8606..00000000
--- a/.changeset/change-position.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-type: minor
----
-
-`changePosition` takes two numbers as well as a vector.
-
-Moving by an amount worked only when the amount was already a `Vector2`, though
-`setPosition` has taken two numbers all along.
diff --git a/.changeset/colour-prints.md b/.changeset/colour-prints.md
deleted file mode 100644
index 25528d65..00000000
--- a/.changeset/colour-prints.md
+++ /dev/null
@@ -1,10 +0,0 @@
----
-type: patch
----
-
-A `Color` says which colour it is.
-
-Printing one gave `org.openpatch.scratch.Color@35432107`, which is the first
-thing anyone tries when a tint looks wrong. It now reads
-`Color[r=255.0, g=128.0, b=0.0]`, and two colours with the same channels are
-equal.
diff --git a/.changeset/count-is-an-int.md b/.changeset/count-is-an-int.md
deleted file mode 100644
index 3683f097..00000000
--- a/.changeset/count-is-an-int.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-type: patch
----
-
-`Stage.count` returns an `int`.
-
-It returned the `long` a `Stream` happened to hand back, so
-`int coins = myStage.count(Coin.class)` did not compile.
diff --git a/.changeset/ghost-effect.md b/.changeset/ghost-effect.md
deleted file mode 100644
index 734fb108..00000000
--- a/.changeset/ghost-effect.md
+++ /dev/null
@@ -1,13 +0,0 @@
----
-type: minor
----
-
-Transparency is the Scratch ghost effect.
-
-It ran from 0 to 255, where 0 was invisible and 255 the solid sprite you start
-with — upside down and on the wrong scale next to the `set [ghost v] effect to`
-shown beside it. It now runs 0 to 100, 0 solid and 100 invisible, and a value
-outside that is pinned rather than wrapped.
-
-`mySprite.setTransparency(50)` used to be nearly invisible; it is now half
-see-through.
diff --git a/.changeset/named-stages-removed.md b/.changeset/named-stages-removed.md
deleted file mode 100644
index 8888792f..00000000
--- a/.changeset/named-stages-removed.md
+++ /dev/null
@@ -1,16 +0,0 @@
----
-type: minor
----
-
-`Window.addStage`, `switchStage` and `removeStage` are gone.
-
-Deprecated since 4.0.0 in favour of `setStage`, which holds the stage you give it
-rather than a name you have to remember, and `transitionToStage` when the change
-should fade.
-
- myWindow.addStage("level", level); // was
- myWindow.switchStage("level");
- myWindow.setStage(level); // now
-
-`removeStage` needs no replacement: a stage the window is not showing does not
-run.
diff --git a/.changeset/scratch-mod.md b/.changeset/scratch-mod.md
deleted file mode 100644
index 0c175a7f..00000000
--- a/.changeset/scratch-mod.md
+++ /dev/null
@@ -1,10 +0,0 @@
----
-type: minor
----
-
-Operators.mod answers the way the Scratch block does.
-
-It was Java's `%`, whose answer takes the sign of the first input, so
-`mod(-7, 3)` was -1 where the block says 2. The answer now takes the sign of the
-second input, which is what makes it wrap a value into a range without a special
-case: `mod(-1, 10)` is 9.
diff --git a/.changeset/stage-effects.md b/.changeset/stage-effects.md
deleted file mode 100644
index 4b2d7e8d..00000000
--- a/.changeset/stage-effects.md
+++ /dev/null
@@ -1,9 +0,0 @@
----
-type: patch
----
-
-A stage's ghost and colour effects survive a change of backdrop.
-
-`setTransparency`, `setTint` and `changeTint` reached only the backdrop that was
-showing, so switching backdrop quietly undid them. They now reach all of them, as
-a sprite's have always reached all its costumes.
diff --git a/.changeset/text-align-moves-the-frame.md b/.changeset/text-align-moves-the-frame.md
deleted file mode 100644
index 9f7c3ad3..00000000
--- a/.changeset/text-align-moves-the-frame.md
+++ /dev/null
@@ -1,10 +0,0 @@
----
-type: patch
----
-
-`setAlign` moves the frame, not only the words inside it.
-
-The frame always started at the position it was given, so a centred box was not
-centred on anything and its words sat half outside it. An aligned text also sat a
-line too high, because choosing a horizontal alignment put the vertical one back
-to the baseline.
diff --git a/.changeset/text-box-corners.md b/.changeset/text-box-corners.md
deleted file mode 100644
index 0443b094..00000000
--- a/.changeset/text-box-corners.md
+++ /dev/null
@@ -1,9 +0,0 @@
----
-type: patch
----
-
-A framed text is rounded on all four corners.
-
-Only the top two were. The stage's display line keeps its bottom two square,
-because they sit on the edge of the stage where a curve would only show what is
-behind it.
diff --git a/.changeset/text-frame-fits-the-words.md b/.changeset/text-frame-fits-the-words.md
deleted file mode 100644
index f09099d7..00000000
--- a/.changeset/text-frame-fits-the-words.md
+++ /dev/null
@@ -1,10 +0,0 @@
----
-type: patch
----
-
-A framed text is drawn around its words rather than filling the width it was given.
-
-The width is where the words wrap. `new Text("Hello World", 0, 0, 400)` came out
-as a mostly empty 400 pixel frame running off the side of the stage; it now comes
-out as wide as "Hello World". The stage's display line still reaches from edge to
-edge, because it is a band rather than a label.
diff --git a/.changeset/text-get-style.md b/.changeset/text-get-style.md
deleted file mode 100644
index 8ee71ab8..00000000
--- a/.changeset/text-get-style.md
+++ /dev/null
@@ -1,7 +0,0 @@
----
-type: minor
----
-
-`Text.getStyle()` answers with the style a text is drawn in.
-
-`setStyle` had no counterpart.
diff --git a/.changeset/text-has-a-style.md b/.changeset/text-has-a-style.md
deleted file mode 100644
index c1566c92..00000000
--- a/.changeset/text-has-a-style.md
+++ /dev/null
@@ -1,10 +0,0 @@
----
-type: patch
----
-
-A text built with words can be drawn at all.
-
-`new Text(words, x, y, width)` never set a style, and drawing switches on one, so
-a text built that way threw on every frame - from inside the loading screen,
-which the program then never left. A white stage, nothing drawn, and no error
-where anyone would look for it.
diff --git a/.changeset/text-shows-its-words.md b/.changeset/text-shows-its-words.md
deleted file mode 100644
index ce401fd8..00000000
--- a/.changeset/text-shows-its-words.md
+++ /dev/null
@@ -1,10 +0,0 @@
----
-type: patch
----
-
-A text shows the words it was built with.
-
-`new Text("Hello World", 0, 0, 400)` put nothing on the stage - the constructor
-left it hidden until `showText()`. A text built with words is visible now; one
-built with nothing to say still starts hidden, which is what a speech bubble
-waiting for `say()` wants.
diff --git a/.changeset/text-size-is-not-remembered.md b/.changeset/text-size-is-not-remembered.md
deleted file mode 100644
index 0c28483a..00000000
--- a/.changeset/text-size-is-not-remembered.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-type: patch
----
-
-Drawing a text no longer writes its measured size back into it.
-
-A box drawn after a bubble came out the size of that bubble, and `getWidth()`
-answered with whatever was last drawn rather than the width that was set.
diff --git a/.changeset/text-standalone-bubbles.md b/.changeset/text-standalone-bubbles.md
deleted file mode 100644
index 22ba9fe4..00000000
--- a/.changeset/text-standalone-bubbles.md
+++ /dev/null
@@ -1,9 +0,0 @@
----
-type: patch
----
-
-Speech and thought bubbles work on a text of their own.
-
-`setStyle(TextStyle.SPEAK)` on a text you placed yourself drew nothing: the
-drawing gave up unless the text belonged to a sprite, because it took its
-position from that sprite. Such a text now keeps the position it was given.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ab382d5a..92eeb72f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,9 +1,147 @@
---
name: Changelog
-index: 64
+index: 65
lang: en
---
+## 5.1.0
+
+
+
+A text shows the words it was built with.
+
+`new Text("Hello World", 0, 0, 400)` put nothing on the stage - the constructor
+left it hidden until `showText()`. A text built with words is visible now; one
+built with nothing to say still starts hidden, which is what a speech bubble
+waiting for `say()` wants.
+
+
+`Text.getStyle()` answers with the style a text is drawn in.
+
+`setStyle` had no counterpart.
+
+
+`changePosition` takes two numbers as well as a vector.
+
+Moving by an amount worked only when the amount was already a `Vector2`, though
+`setPosition` has taken two numbers all along.
+
+
+Transparency is the Scratch ghost effect.
+
+It ran from 0 to 255, where 0 was invisible and 255 the solid sprite you start
+with — upside down and on the wrong scale next to the `set [ghost v] effect to`
+shown beside it. It now runs 0 to 100, 0 solid and 100 invisible, and a value
+outside that is pinned rather than wrapped.
+
+`mySprite.setTransparency(50)` used to be nearly invisible; it is now half
+see-through.
+
+
+A `Color` says which colour it is.
+
+Printing one gave `org.openpatch.scratch.Color@35432107`, which is the first
+thing anyone tries when a tint looks wrong. It now reads
+`Color[r=255.0, g=128.0, b=0.0]`, and two colours with the same channels are
+equal.
+
+
+A built-in sprite name works everywhere a picture is named.
+
+`new Sprite("player", "slimeGreen")` threw `Could not load image: slimeGreen`:
+the constructor took a path where `addCostume()` took either. It now takes
+either, as do `Stage.setCursor`, `Window.useSplashLogo` and
+`Sprite.addCostumes`. A string with a file extension is still a path.
+
+
+A framed text is rounded on all four corners.
+
+Only the top two were. The stage's display line keeps its bottom two square,
+because they sit on the edge of the stage where a curve would only show what is
+behind it.
+
+
+Speech and thought bubbles work on a text of their own.
+
+`setStyle(TextStyle.SPEAK)` on a text you placed yourself drew nothing: the
+drawing gave up unless the text belonged to a sprite, because it took its
+position from that sprite. Such a text now keeps the position it was given.
+
+
+Speech and thought bubbles hang off the sprite's hitbox.
+
+They were placed from the size of the costume, which is usually a canvas bigger
+than what is painted on it, so the bubble floated up and to the right of its
+sprite with its tail pointing at nothing. It now sits on the top right corner of
+the hitbox. For the built-in slime that moves it 14 pixels left and 72 down, onto
+its shoulder.
+
+
+`setAlign` moves the frame, not only the words inside it.
+
+The frame always started at the position it was given, so a centred box was not
+centred on anything and its words sat half outside it. An aligned text also sat a
+line too high, because choosing a horizontal alignment put the vertical one back
+to the baseline.
+
+
+`Stage.count` returns an `int`.
+
+It returned the `long` a `Stream` happened to hand back, so
+`int coins = myStage.count(Coin.class)` did not compile.
+
+
+A stage's ghost and colour effects survive a change of backdrop.
+
+`setTransparency`, `setTint` and `changeTint` reached only the backdrop that was
+showing, so switching backdrop quietly undid them. They now reach all of them, as
+a sprite's have always reached all its costumes.
+
+
+`Window.addStage`, `switchStage` and `removeStage` are gone.
+
+Deprecated since 4.0.0 in favour of `setStage`, which holds the stage you give it
+rather than a name you have to remember, and `transitionToStage` when the change
+should fade.
+
+ myWindow.addStage("level", level); // was
+ myWindow.switchStage("level");
+ myWindow.setStage(level); // now
+
+`removeStage` needs no replacement: a stage the window is not showing does not
+run.
+
+
+Operators.mod answers the way the Scratch block does.
+
+It was Java's `%`, whose answer takes the sign of the first input, so
+`mod(-7, 3)` was -1 where the block says 2. The answer now takes the sign of the
+second input, which is what makes it wrap a value into a range without a special
+case: `mod(-1, 10)` is 9.
+
+
+Drawing a text no longer writes its measured size back into it.
+
+A box drawn after a bubble came out the size of that bubble, and `getWidth()`
+answered with whatever was last drawn rather than the width that was set.
+
+
+A framed text is drawn around its words rather than filling the width it was given.
+
+The width is where the words wrap. `new Text("Hello World", 0, 0, 400)` came out
+as a mostly empty 400 pixel frame running off the side of the stage; it now comes
+out as wide as "Hello World". The stage's display line still reaches from edge to
+edge, because it is a band rather than a label.
+
+
+A text built with words can be drawn at all.
+
+`new Text(words, x, y, width)` never set a style, and drawing switches on one, so
+a text built that way threw on every frame - from inside the loading screen,
+which the program then never left. A white stage, nothing drawn, and no error
+where anyone would look for it.
+
+
## 5.0.3
diff --git a/pom.xml b/pom.xml
index b74d8713..74fda48f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
org.openpatch
scratch
- 5.0.3
+ 5.1.0
jar
Scratch for Java