Skip to content

Instantly share code, notes, and snippets.

@mworzala
Last active June 28, 2024 13:04
Show Gist options
  • Save mworzala/d0afb4010f289df3a306116159b1fc0c to your computer and use it in GitHub Desktop.
Save mworzala/d0afb4010f289df3a306116159b1fc0c to your computer and use it in GitHub Desktop.

Minestom 1.20.6

The 1.20.6 update for Minestom comes (as usual) with some breaking changes both from the protocol and api improvements for the library. The major changes are as follows:

  1. Hephaistos removed in favor of Adventure NBT.
  2. Item components
  3. Pathfinding
  4. Dynamic registry improvements

Note about inventory rework

The Inventory Rework PR was previously part of the 1.20.5 branch. It is in the middle of a rework, and is not quite ready for this version. We are still planning to include it in a later version (most likely 1.21.1). If you already updated and have to revert, sorry for the trouble!

NBT Library Swap

We are now using adventure-nbt as the NBT library internally. As a nice side effect, Minestom does not ship with the Kotlin standard library anymore :). In many cases this change should not affect existing codebases using the Tag api, which is unchanged. A brief overview of the api is provided below:

// Like Hephaistos, all adventure-nbt types are immutable.

// The basic primitive is BinaryTag, as opposed to the NBT type in Hephaistos

// The basic types are all constructed with a similarly named static factory function.
ByteBinaryTag myByte = ByteBinaryTag.byteBinaryTag((byte) 2);
StringBinaryTag myString = StringBinaryTag.stringBinaryTag("Hello, Adventure!!");
IntArrayBinaryTag myIntArray = IntArrayBinaryTag.intArrayBinaryTag(new int[]{1, 2, 3});

// Compounds can be constructed either with a factory function or builder
CompoundBinaryTag myCompound = CompoundBinaryTag.from(Map.of("key", myString));
CompoundBinaryTag myCompound = CompoundBinaryTag.builder()
		.putString("key", "value")
		.build();

// Lists can be constructed similarly
ListBinaryTag myList = ListBinaryTag.from(List.of(myString));
ListBinaryTag myList = ListBinaryTag.builder(BinaryTagTypes.STRING)
    .add(myString)
    .build();
// In the builder example, passing the list type is optional and will be inferred otherwise.

Serialization in adventure-nbt currently only supports serialization to and from compounds (known issues, should be fixed in a future version). Minestom provides a small api on top to handle extra cases. This api will be removed in the future when adventure-nbt has proper support.

// Binary
BinaryTagReader reader = new BinaryTagReader(someDataInput);
BinaryTag tag = reader.readNameless(); // throws IOException
Map.Entry<String, BinaryTag> namedTag = reader.readNamed(); // throws IOException

BinaryTagWriter writer = new BinaryTagWriter(someDataOutput);
writer.writeNameless(IntBinaryTag.intBinaryTag(1)); // throws IOException
writer.writeNamed(Map.entry("key", IntBinaryTag.intBinaryTag(1))); // throws IOException

// SNBT
BinaryTag tag = TagStringIOExt.readTag("1"); // throws IOException

String raw = TagStringIOExt.writeTag(IntBinaryTag.intBinaryTag(1));

The Anvil loader has been rewritten (it used many components from Hephaistos). In basic testing the new version takes around 1/5 the time to load chunks. It targets the current anvil version only (as opposed to Hephaistos which handled upgrades in some cases but not others), so please make sure to upgrade your world using a vanilla client/server first if you run into issues. If you do encounter issues, please report them on GitHub or in Discord!

Item Components

As of Snapshot 24w09a (should read for more context if you have not), notable item meta NBT tags are removed in favor of typed item components. Accordingly, ItemMeta and all related types have been removed, and ItemComponent has been added.

Note: ItemComponent holds all of the definitions related to items, however DataComponent is the underlying type for all components. This was done under the assumption that Mojang will reuse DataComponent for other data similar to on Bedrock Edition (this is semi-confirmed by Mojang mappings calling it net.minecraft.core.component.DataComponent). The terms ItemComponent, DataComponent and component are used interchangeably below.

The api for working with components on items is based on the following relevant functions. All DataComponent implementation classes are immutable (records):

ItemStack#get(DataComponent<T>) // @Nullable T
ItemStack#get(DataComponent<T>, T) // @NotNull T

ItemStack#with(DataComponent<T>, T)
ItemStack#without(DataComponent)
ItemStack.Builder#set(DataComponent<T>)
ItemStack.Builder#remove(DataComponent<T>)

A full list of item components can be found on the Minecraft wiki, however I will highlight some of the notable ones below:

// Custom name
itemStack.withDisplayName(myComponent); // Old
itemStack.with(ItemComponent.CUSTOM_NAME, myComponent); // New

// Lore
itemStack.withLore(myComponentList); // Old
itemStack.with(ItemComponent.LORE, myComponentList); // New

// Custom model data
itemStack.with(meta -> meta.customModelData(1)); // Old
itemStack.with(ItemComponent.CUSTOM_MODEL_DATA, 1); // New

// Item hide flags
itemStack.with(meta -> meta.hideFlag(ItemHideFlag.HIDE_ENCHANTS)); // Old
itemStack.with(ItemComponent.ENCHANTMENTS, new EnchantmentList(myEnchantmentMap, false));
// Note that the hide flag is always inside of the associated component, rather than together in one bit flag.
// A shorthand for modifying a component (without adding it if not present) is using ItemStack#with(ItemComponent<T>, UnaryOperator<T>):
itemStack.with(ItemComponent.ENCHANTMENTS, enchants -> enchants.withTooltip(false));

The old NBT tag used for user defined data is now in the CUSTOM_DATA component. The old ItemStack functions for interacting with the Tag api have been preserved, and read from/write to the CUSTOM_DATA component.

Pathfinding

We have removed the current pathfinding library Hydrazine in favor of our own implementation. The high-level pathfinding API has not been changed, so unless you depend on some internals or hydrazine specifics, this should not affect your code. You should see significantly better pathing results now, however this is a first version and pathfinders have a lot of specifics/edge cases so we are expecting to find some issues.

As a nice side effect of this change, we now no longer have any dependencies on Jitpack, so you can remove that from your repositories! Also that pesky (irrelevant) CVE is now gone :)

Registry Changes

Dynamic registries (Chat type, dimension type, biome, damage type, trim material, trim pattern, banner pattern, wolf variant) are now all instances of DynamicRegistry, which replace the old manager style. All of these registries now load the vanilla data by default (eg for biomes, all of the vanilla biomes will be loaded by default), and all associated types have generated constants (some did not previously).

Dynamic registry entries are now no longer represented by their record, instead a wrapper around a namespace id is used to reference the object with that ID. All generated constants are now DynamicRegistry.Key<T> instances, and relevant methods take the same type. For example, biome usage has changed in the following way:

void setBiome(Point pos, Biome biome); // Old
void setBiome(Point pos, DynamicRegistry.Key<Biome>); // New

DynamicRegistry has an api for registering new entries. You can also overwrite and remove entries but you must first set a system property because these operations are inherently unsafe. See the associated method for more details.

In all cases the APIs of the dynamic registry types (like Biome) have been standardized. This has resulted in some breaking field renames and cleanup to match vanilla naming.

Misc Changes

The following are some smaller but still notable changes:

  • Minestom always enables the new optional strictErrorHandling flag sent during login. This will be removed in 1.21 so does not seem worth adding a flag for. If you get a client disconnect for Network Protocol Error, this is the reason.
  • StackingRule has been removed and all checks are now based on the MAX_STACK_SIZE component and ItemStack#isSimilar tests.
  • Particle data types now have their own concrete Particle implementations with some utility functions for adding the relevant data. For example, block particles now can be created with Particle.BLOCK.withBlock(Block.STONE).
  • Attribute types are now generated from vanilla data. In the API this just means some names have been adjusted, generally including GENERIC_ at the start, eg Attribute.MOVEMENT_SPEED -> Attribute.GENERIC_MOVEMENT_SPEED. They are also now located inside the entity package.
  • Enchantment is now inside the item.enchant package.
  • LivingEntity fire state is now based on ticks instead of wall-clock time.
  • Food/potion eat duration now matches vanilla by default and is based on ticks instead of wall-clock time. Player defaultEatingTime has been removed.
  • Cookies may be set on the player connection using PlayerConnection#storeCookie and PlayerConnection#fetchCookie.
  • RecipeTypes are now generated from vanilla data. Some names have been adjusted.
  • The current game data version is now present as a constant in MinecraftServer.
  • SoundEvent now encapsulates both custom (resource pack) sounds and vanilla sounds. Cases where both were taken (usually as @Nullable SoundEvent, @Nullable String, @Nullable Float) should be replaced by the associated SoundEvent constant or SoundEvent.of(String, Float) for custom sounds.
  • EquipmentSlot#fromAttributeSlot has been removed in favor of AttributeSlot#equipmentSlots which can return multiple entries.
  • EntityPropertiesPacket was renamed to EntityAttributesPacket to better represent the content and match the Mojang mapping name.
  • Living entity meta potion color has been replaced with a list of Particles inline with the associated protocol change.
  • TextDisplayMeta#getTextOpacity is now a byte inline with the protocol.
  • The old ChunkGenerator api has been removed. The new Generator should be used instead.
  • BlockPlacementRule now receives the ItemStack used to place the block, rather than the ItemMeta which has been removed.
  • Inline with the related protocol change, it is now invalid to put air in a Recipe and doing so will generate an exception.
  • Factor data is gone in Potion effects (previously used for the darkness effect).
  • By default chat will no longer be cleared during the configuration phase, use AsyncPlayerConfigurationEvent#setClearChat(boolean) to reenable this behavior.
  • The anvil input packet (ClientNameItemPacket) is now handled and calls the associated PlayerAnvilInputEvent.
  • Instance time synchronization methods are now based on ticks instead of wall time. The new methods are Instance#getTimeSynchronizationTicks and Instance#setTimeSynchronizationTicks.
  • LivingEntity fire is now based on ticks instead of wall time. The old fire event is now split into EntitySetFireEvent and EntityExtinguishFireEvent for each end of it.
  • WorldBorder is now an immutable record. You can reuse the same world border safely, and apply to an Instance with a transition period. When comparing against the world border, you should always fetch the most up to date value with Instance#getWorldBorder in case it is mid-transition.
  • BlockDisplayMeta now uses Block directly rather than a state id as an integer.
  • Block#stateId and Block#fromStateId now work with integers instead of floats.
  • Entities are no longer tracked globally. To fetch an entity by its ID or UUID, use Instance#getEntityById or Instance#getEntityByUuid respectively. This means that two different entities with the same UUID may exist in two different instances at the same time. It is never valid for two entities to have the same UUID in the same instance.
  • Entity#setUuid has been removed, along with AsyncPlayerPreLoginEvent#setUuid. A UuidProvider or online mode/proxy forwarding should be used to set a player UUID. Entity UUIDs should be set upon construction and constant.
  • Removed the minestom.experiment.pose-updates system property. Player pose updates are now handled by default.

Internal BinaryTagSerializer API

An API has been added internally for de/serializing from NBT (particularly, item components). This API should not be considered ready for external use, it will almost certainly have breaking changes without warning. (Don’t) Use at your own risk.

Misc Future Tasks

  • Receiving transfers from other servers is not currently supported in Minestom. This will be added in a future PR. It is possible to transfer a player from a Minestom server by sending the packet, eg player.sendPacket(new TransferPacket(“localhost”, 25566));.
  • We are now capable of more properly handling passenger/vehicle offsets on entities. The relevant data is now present in the data repository, however it is not in use in Minestom yet. This will be done in the future, and should be a non-breaking change.

Big thank you to all the people who tried the unstable branch, and as always if you run into bugs please report them on GitHub or in the Discord server!

@GoldenStack
Copy link

minestorm

@TheMode
Copy link

TheMode commented Jun 10, 2024

How can I install factions plugin?

@GoldenStack
Copy link

How can I install factions plugin?

Yo can intall fation plugn by plgnunging the functions. The factons. Moev the plugn the gpljn funactions theo the

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment