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

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

agnor99
Copy link

@agnor99 agnor99 commented Oct 3, 2023

This adds documentation for the vanilla attribute system


Preview URL: https://pr-15.neoforged-docs-previews.pages.dev

Copy link
Contributor

@ChampionAsh5357 ChampionAsh5357 left a comment

Choose a reason for hiding this comment

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

Take a look at #14 for the current draft standards.

In general, I think this needs more work on explaining what an attribute is, why do we use it, and how we do so.

@@ -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.

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.

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."

Comment on lines 6 to 24
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

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.

Comment on lines +26 to +35
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 |
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.

Comment on lines 40 to 42
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.
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.

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)

-----------

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?

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.

-----------

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.

Operation can be explained in a subcategory here.

Choose a reason for hiding this comment

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


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.
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.

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

Comment on lines 47 to 50
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.

Comment on lines 55 to 57
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?

@neoforged-pages-deployments neoforged-pages-deployments bot deployed to neoforged-docs-previews (Preview) October 3, 2023 20:10 Active
@neoforged-pages-deployments
Copy link

Deploying with Cloudflare Pages

Name Result
Last commit: 63dc054eac12bfd5a641c5aa0c0033cbe8ae1730
Status: ✅ Deploy successful!
Preview URL: https://1400ea5a.neoforged-docs-previews.pages.dev
PR Preview URL: https://pr-15.neoforged-docs-previews.pages.dev

@Shadows-of-Fire
Copy link

Fair amount of work probably needed here.

The current state is unfortunately inbetween "too technical" and "too simple" in that it is not technical enough for advanced users to gain anything that they would not have inferred on their own, but also too verbose for new users.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants