- 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
ChatPreviewS2CPacketwhich 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
SignedChatMessagesent by the client, and the response text can now be considered signed - Server calls
ChatDecorator#decorateagain; 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#damagewith fire damage will no longer check that the entity is fire-immune, since it prevented the damage from provoking the mob. Together with thisEntity#isInvulnerableTowas updated to returntruefor fire damages to fire-immune mobs. Screen#sendMessagewas removed. UseClientPlayerEntity#sendMessageinstead.WarningScreen#parentwas removed. Subclasses need to track it themselves.EnumArgumentType,BlockMirrorArgumentType, andBlockRotationArgumentTypewere added.DamageSource#SONIC_BOOMbecame a static methodsonicBoomallowing attacker to be specified.PacketByteBufnow contains methods for reading and writingRegistryKey,GlobalPos,Instant, andPublicKey.GameJoinS2CPacket'sdimensionTypefield is nowRegistryKeyinstead ofRegistryEntry.- Invalid public keys no longer cause disconnection in local integrated server.
ServerMetadataS2CPacketwas 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. initAndGetDefaultmethods now take theRegistryto add.Texts#hasTranslationwill work properly again. Previously it was alwyas returningtrue.Codecsnow containsBASE_64andTAG_ENTRYcodecs.AbstractRandomnow creates the new random using seed uniquifier withRandomSeed#getSeed. Previously it used system nano time only.BlockMirrorandBlockRotationnow implementStringIdentifiableand have codecs.Util#mapandUtil#mapOrElsewere added, which is a nullable equivalent ofoptional.map(...)andoptional.map(...).orElse(...).