Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

create attribute documentation #15

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions docs/entities/_category_.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"label": "Entities"
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New line at EOF.

59 changes: 59 additions & 0 deletions docs/entities/attributes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
Attributes
==========

Attributes are ways to modify specific values for living entities in a mod compatible way.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's not really what an attribute is. That's what we use it for, yes, but it's not the intended purpose. Iirc, attributes are a property defined on an entity that is meant to apply the greatest modifier without stacking to the player.

Please correct me if I'm wrong, I can't look on my computer because it's a hot brick.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nope, it's not about the greatest modifier, all active AttributeModifiers are considered. addition stacks by just addition, multiply_base stacks by adding the factors (+20% and +20% combine to +40%) and multiply_total stacks by multiplication (+20% and +20% combine to +44%)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay. So the AttributeMap has a map of Attributes to AttributeInstances, which in turn hold a set of AttributeModifiers, unique by their id, grouped by operation.

Okay then, then it should still be something like: attributes are a property defined on an entity that can be modified by many different elements at the same time. Each element can be applied and removed depending on their intent.

There's probably a better way to word that, but it's what I'm thinking rn.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An apt description is "Attributes are properties of an entity which correspond to a value. This value can be modified by multiple sources at once through Attribute Modifiers, allowing for simple cross-mod compatibility."


Existing Attributes
-----------
Vanilla adds the following attributes:

| Attribute | Description |
|-------------------------------|----------------------------------------------------------------------------------------------|
| `MAX_HEALTH` | how much health the entity has |
| `FOLLOW_RANGE` | how far the entity can track something |
| `KNOCKBACK_RESISTANCE` | how strong knockback is reduced. Ranged between 0 and 1, 1 cancelling all knockback. |
| `MOVEMENT_SPEED` | how fast the entity moves |
| `FLYING_SPEED` | The flying speed of the entity. Not applicable to players who fly with the elytra |
| `ATTACK_DAMAGE` | how much damage the entity deals when attacking |
| `ATTACK_KNOCKBACK` | how much knockback the entity causes when physically attacking |
| `ATTACK_SPEED` | how many full damage attack the entity deals per second |
| `ARMOR` | how many armor points the entity has and how resistant it is to attacks |
| `ARMOR_TOUGHNESS` | how resistant the entity is to strong attacks |
| `LUCK` | changes the chance for treasure, junk and normal fishing loottables |
| `SPAWN_REINFORCEMENTS_CHANCE` | how likely a zombie spawns reinforcements when attacked |
| `JUMP_STRENGTH` | how high the entity jumps. Only applicable for horse like more (including mules and camels). |
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have no idea how useful this is. This makes sense in parchment, but I feel like this could also just be said it's in the attributes file and list some examples.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do believe that the list of attributes and what they do is useful. There are already parchment comments for them, but giving people examples for what mojang and neo use attributes for, so people can easier understand, what things attributes can be used for and therefore be used for their use cases

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is one of those instances where I'm inclined to agree that the docs should delegate to the code for listing the attributes. This is almost guaranteed to go stale, while a reference to the Attributes class will always be accurate.


NeoForge adds the following attributes:

| Attribute | Description |
|------------------------|------------------------------------------------------------------------|
| `SWIM_SPEED` | how fast the entity swims |
| `NAMETAG_DISTANCE` | how far the nametag can be seen for this entity |
| `ENTITY_GRAVITY` | how fast the entity accelerates when not on ground |
| `BLOCK_REACH` | how far the player can interact with the world |
| `ENTITY_REACH` | how far the player can interact with entities |
| `STEP_HEIGHT_ADDITION` | how high the entity can walk up blocks in addition to Entity#maxUpStep |
Comment on lines +26 to +35
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, same issue here. This one makes more sense though to have in the documentation.


Attribute, AttributeInstance and AttributeModifier
-----------

Attributes have to be [registered][registration] and are used to look up the current `AttributeInstance` for a given LivingEntity. The `AttributeInstance` holds all `AttributeModifier` currently active on the entity.
AttributeModifiers require a UUID that should be unique to this modifier. It's used to ensure that an `AttributeModifier` can only be applied once to a LivingEntity. You should generate a random one once and then hardcode it. They also require an Operation and an amount to perform the calculation. How the calculation works can be read in the next section.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why should I hardcode the UUID?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The question of "should I hardcode the UUID" is implementation dependent on the answer of what will you need to do with that modifier in the future.

If you are performing a one-off permanent modifier addition (to say, an entity when it is being spawned), there is no need to use a static UUID.
If you are adding attribute modifiers to an item, you must use a static UUID otherwise the modifier will not be removed when the item is unequipped.

Attributes also only permit one modifier with the same UUID (though one UUID can be used across Attributes), so it can be useful to prevent re-application.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Operation can be explained in a subcategory here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The value of an `Attribute` for a given `LivingEntity` can be obtained by the `AttributeMap` for the LivingEntity and getting the `AttributeInstance` from it and then calling `AttributeInstance#getValue`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably best to give an example on how to do so.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is overly verbose IMO. The quick method to retrieve the value of an attribute is LivingEntity#getAttributeValue(Attribute)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Example. Also, I don't think this is as useful as explaining what methods in the entity provide this.


Operations
-----------

AttributeInstances can have 3 different operations, `ADDITION`, `MULTIPLY_BASE` and `MULTIPLY_TOTAL`.
First the default value is used and all `ADDITION`-Modifiers are added to it. This is the base value.
`MULTIPLY_BASE`-Modifiers are applied next, they multiply the base value with 1 + the sum of the `MULTIPLY_BASE` modifiers.
`MULTIPLY_TOTAL`-Modifiers are applied last, they multiply the value created with 1+modifier each.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Show maths.


Applying AttributeModifier
-----------

AttributeModifiers can be applied for held items and worn armor.
Changing the AttributeModifier for custom Items can be achieved by overriding IForgeItem#getAttributeModifiers. You can also apply AttributeModifiers to ItemStacks by calling ItemStack#addAttributeModifier.
Attribute Modifiers can also be added and removed to LivingEntities directly by obtaining the `AttributeMap` with `LivingEntity#getAttributes` and getting the AttributeInstance with `AttributeMap#getInstance`. You can then remove and add them with the methods present on the AttributeInstance.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Examples. This is highly unclear. Also, what happened to potions or effects?


[registration]: ../concepts/registries.md