- Crash when warden gets angry at multiple mobs MC-251641
Note that for convenience, the following will use proposed Yarn names that are not yet merged.
Chat Preview was added, allowing server-side decorated messages to be signed. Basically this works like this:
- Server enables chat preview (with
server.properties
) - Client joins
- Warning screen appears (that the server can read chat message before they are sent)
- Client types on chat screen
- New packet,
QueryChatPreviewC2SPacket
, is sent after 100ms - The query is stored in
ChatPreview
- Server calls
ChatDecorator#decorate
- Server responds with
ChatPreviewS2CPacket
which contains the decorated text, the query ID, and the query string - Chat preview appears above chat screen (like command parsing error)
- After a few milliseconds, the chat consumes the response - this is done so that the player has time to cancel the submission, otherwise with precise timing the player might not see the preview.
- Steps 4-9 repeated except the interval is now 1000ms
- The latest response text is included in the
SignedChatMessage
sent by the client, and the response text can now be considered signed - Server calls
ChatDecorator#decorate
again; If the returned message differs from the one sent by the client, it will discard the message because it means the client has attempted to send arbitraryText
.
As seen above, chat preview is a security feature, the compromise between messages being unsigned and messages being non-decoratable - the server decorates the message and sends that as a preview, and the player can either accept the previewed text (which is used as the chat message as-is) or reject it (by simply not sending). Note that the client can disable chat preview which makes the server-decorated message unsigned.
Given the relatively common nature of the preview query, and the requirement of decorating the message in the same way between the preview and the submission, caching the decorated data is highly recommended.
Of course, you can still use other (not recommended) ways of transformation - the server, for example, can strip signatures or send the message as a game message instead of chat message. However, this change also came with a new client-side option to hide unsigned messages and only show signed ones (or, in case of partially-signed, server-side-decorated message, the signed, raw message). It's therefore recommended to make sure the signature stays valid. Vanilla chat filter will filter the signed content only.
Client-side transformation via Decoration/custom MessageType still works. Note that there was a code refactor around these: the registry is now properly managed by the DRM, so the registry previously obtained via Registry.MESSAGE_TYPE
must now be obtained from the DRM (or BuiltinRegistries
). Registering new message types will now use BuiltinRegistries.add
like other dynamic registries.
Data generators now have "path resolvers". This is stored in the generator and can be created using DataGenerator#createPathResolver
. To get the path, use resolveRootDirectoryPath
. With this change, various path
parameters in datagen methods have been removed.
Path path = this.generator.resolveRootDirectoryPath(DataGenerator.OutputType.REPORTS).resolve("blocks.json");
POI tags have been added - and together with this, code that previously took PointOfInteresetType
/Predicate<PointOfInterestType>
will now take Predicate<RegistryEntry<PointOfInterestType>>
, allowing multiple types and tags to be referenced. Fields and methods taking that instance will now also ask for the predicate.
// Old
poiStorage.getPositions(PointOfInterestType.HOME.getCompletionCondition(), ...);
// New
poiStorage.getTypesAndPositions(entry -> entry.matchesKey(PointOfInterestTypes.HOME), ...)
PointOfInterestTypes
is a new class holding registry keys for the point of interest types. Notably, this class is also responsible for registering new PointOfInterestType
; the helper methods from Fabric API have been removed and instead the register
method (access-widened by Fabric API) should be used.
There is also a change to the registry of PointOfInterestType
- it is no longer a DefaultedRegistry
.
Let's mention changes to VillagerProfession
here as well; it's now a record and contains acquirableJobSite
field which is a POI entry predicate used by unemployed villagers to see which job sites they can acquire. To register
Tag
class was removed. The functionalities were already moved to the registry/TagKey
in 1.18.2. The inner classes, which are still in use, have been moved to TagBuilder
/TagEntry
. The remaining usages in functions now use Collection
.
- Vanilla code that called
Entity#damage
with fire damage will no longer check that the entity is fire-immune, since it prevented the damage from provoking the mob. Together with thisEntity#isInvulnerableTo
was updated to returntrue
for fire damages to fire-immune mobs. Screen#sendMessage
was removed. UseClientPlayerEntity#sendMessage
instead.WarningScreen#parent
was removed. Subclasses need to track it themselves.EnumArgumentType
,BlockMirrorArgumentType
, andBlockRotationArgumentType
were added.DamageSource#SONIC_BOOM
became a static methodsonicBoom
allowing attacker to be specified.PacketByteBuf
now contains methods for reading and writingRegistryKey
,GlobalPos
,Instant
, andPublicKey
.GameJoinS2CPacket
'sdimensionType
field is nowRegistryKey
instead ofRegistryEntry
.- Invalid public keys no longer cause disconnection in local integrated server.
ServerMetadataS2CPacket
was added. This is sent during the play packet phase, used for servers that haveenable-status=false
.- Profiler for world ticking now works properly. Previously it lacked
pop
. initAndGetDefault
methods now take theRegistry
to add.Texts#hasTranslation
will work properly again. Previously it was alwyas returningtrue
.Codecs
now containsBASE_64
andTAG_ENTRY
codecs.AbstractRandom
now creates the new random using seed uniquifier withRandomSeed#getSeed
. Previously it used system nano time only.BlockMirror
andBlockRotation
now implementStringIdentifiable
and have codecs.Util#map
andUtil#mapOrElse
were added, which is a nullable equivalent ofoptional.map(...)
andoptional.map(...).orElse(...)
.