diff --git a/docs/.style_guide.md b/docs/.style_guide.md index ff170299..542a57ff 100644 --- a/docs/.style_guide.md +++ b/docs/.style_guide.md @@ -11,7 +11,7 @@ For example: Action wheel pages and actions are two separate pages, but knowledg --- -## Global pages +## Global Pages In global pages all functions should be on the right directory sidebar using ###. diff --git a/docs/enums/EntityPoses.md b/docs/enums/EntityPoses.md index 970eee46..8e63a1c1 100644 --- a/docs/enums/EntityPoses.md +++ b/docs/enums/EntityPoses.md @@ -1,4 +1,4 @@ -List of poses a living entity can have, as accessed by :getPose() +List of poses a living entity can have, as accessed by `:getPose()` **Example**: diff --git a/docs/enums/Loop-Modes.md b/docs/enums/Loop-Modes.md index caa76879..876bf28f 100644 --- a/docs/enums/Loop-Modes.md +++ b/docs/enums/Loop-Modes.md @@ -1,6 +1,6 @@ # LoopModes -These are the loop modes a blockbench animation can be set to. They can be initialized in blockbench itself or changed in the code via setLoop(String). +These are the loop modes a Blockbench animation can be set to. They can be initialized in Blockbench itself or changed in the code via `setLoop(String)`. **Example**: diff --git a/docs/enums/ModelPartParentTypes.md b/docs/enums/ModelPartParentTypes.md index b83e342e..be8e92ab 100644 --- a/docs/enums/ModelPartParentTypes.md +++ b/docs/enums/ModelPartParentTypes.md @@ -2,19 +2,17 @@ import Emoji from '@site/src/components/Emoji'; ParentTypes are applied to ModelParts to apply specific transformations, or change how the ModelPart behaves. -## Applying ParentTypes via BlockBench +## Applying ParentTypes through Blockbench -To apply a ParentType through BlockBench, the group name must start with the ParentType. Only groups can have ParentTypes applied via BlockBench. +To apply a ParentType through Blockbench, the group name must start with the ParentType. Only groups can have ParentTypes applied via Blockbench. :::tip -### Keywords - -When setting the ParentType via group names, ParentTypes are commonly referred to as Keywords or BlockBench Keywords. +When setting the ParentType with group names, ParentTypes are commonly referred to as keywords or Blockbench keywords. ::: -**Examples**: +**Keyword Examples** | Blockbench Name | `Head` ParentType | Reason | | --------------------------------------------- | :---------------: | --------------------------------------------------------------------------------- | @@ -22,13 +20,14 @@ When setting the ParentType via group names, ParentTypes are commonly referred t | `HeadPhones` | ✔️ | Group's name starts with a ParentType. | | `MagicHead` | ❌ | Group's name does not start with a ParentType. | | `head` | ❌ | Group's name does not start with a ParentType. `head` is not an alias for `Head`. | -| `Head` | ❌ | ParentTypes can only be applied to groups in BlockBench | +| `Head` | ❌ | ParentTypes can only be applied to groups in Blockbench | --- -## Applying ParentTypes via Script +## Applying ParentTypes through Scripting + +To apply a ParentType through script, [index the ModelPart](../tutorials/ModelPart%20Indexing) you want to set the ParentType of, then call the `setParentType` method on it, passing in a ParentType as a string as the parameter. -To apply a ParentType through script, [index the ModelPart](../tutorials/ModelPart%20Indexing) you want to set the ParentType of, then call the setParentType method on it, passing in a ParentType as a string as the parameter.
After an avatar is loaded, there is no difference between groups, cubes, or bbmodels. Everything is a ModelPart, meaning everything can have a ParentType. **Example**: @@ -42,8 +41,9 @@ models.myOtherModel.Pet:setParentType("World") ## List of ParentTypes -All ParentTypes have an alternate way of spelling it, an alias, though internally they do the same thing. They will be listed just underneath what Figura considers to be the true ParentType.
-Many ParentTypes share similar properties. You can roughly put them into 3 distinct groups: Mimic, Pivot, and Special. These groupings are not recognized by the mod itself and just serve to make explaining similar ParentTypes more convenient.
+All ParentTypes have an alternate way of spelling it, an alias, though internally they do the same thing. They will be listed just underneath what Figura considers to be the true ParentType. + +Many ParentTypes share similar properties. You can roughly put them into 3 distinct groups: Mimic, Pivot, and Special. These groupings are not recognized by the mod itself and just serve to make explaining similar ParentTypes more convenient. --- @@ -53,14 +53,13 @@ Many ParentTypes share similar properties. You can roughly put them into 3 disti - #### `Model` \{#Model} - #### `MODEL` \{#MODEL} -The default ParentType.
-Using this ParentType as a Keyword has no purpose, as groups with no Keyword will have this ParentType, but it can still be used in scripts. +The default ParentType. Using this ParentType as a Keyword has no purpose, as groups with no Keyword will have this ParentType, but it can still be used in scripts. --- ## Player Mimic Types -Player Mimic ParentTypes copy transformations (position, rotation, scale) from elsewhere, typically a Vanilla Part, and apply it to the ModelPart. This allows for a script-free way of making a ModelPart behave like a Vanilla Part. These transformations are added on top of any transformations set via script or transformations set via a BlockBench Animation. To prevent this ParentTypes transformations from being applied while a BlockBench Animation is playing, enable the [Animation's Override property](../start_here/BlockBench#animation-properties). +Player Mimic ParentTypes copy transformations (position, rotation, scale) from elsewhere, typically a Vanilla Part, and apply it to the ModelPart. This allows for a script-free way of making a ModelPart behave like a Vanilla Part. These transformations are added on top of any transformations set via script or transformations set via a Blockbench Animation. To prevent this ParentTypes transformations from being applied while a Blockbench Animation is playing, enable the [Animation's Override property](../start_here/Blockbench#animation-properties). --- @@ -68,7 +67,8 @@ Player Mimic ParentTypes copy transformations (position, rotation, scale) from e - #### `HEAD` \{#HEAD} -Mimics the transformation offsets of the Vanilla HEAD
+Mimics the transformation offsets of the Vanilla `HEAD`. + If there is no ModelParts with the [Skull](#skull) ParentType, ModelParts with this ParentType will replace the Vanilla Skull. --- @@ -77,7 +77,7 @@ If there is no ModelParts with the [Skull](#skull) ParentType, ModelParts with t - #### `BODY` \{#BODY} -Mimics the transformation offsets of the Vanilla BODY +Mimics the transformation offsets of the Vanilla `BODY` --- @@ -85,7 +85,8 @@ Mimics the transformation offsets of the Vanilla BODY - #### `RIGHT_ARM` \{#RIGHT_ARM} -Mimics the transformation offsets of the Vanilla RIGHT_ARM
+Mimics the transformation offsets of the Vanilla `RIGHT_ARM` + This ParentType will appear in First Person under the same conditions as the Vanilla RightArm. --- @@ -94,7 +95,8 @@ This ParentType will appear in First Person under the same conditions as the Van - #### `LEFT_ARM` \{#LEFT_ARM} -Mimics the transformation offsets of the Vanilla LEFT_ARM
+Mimics the transformation offsets of the Vanilla `LEFT_ARM` + This ParentType will appear in First Person under the same conditions as the Vanilla LeftArm. --- @@ -103,7 +105,7 @@ This ParentType will appear in First Person under the same conditions as the Van - #### `RIGHT_LEG` \{#RIGHT_LEG} -Mimics the transformation offsets of the Vanilla RIGHT_LEG +Mimics the transformation offsets of the Vanilla `RIGHT_LEG` --- @@ -111,7 +113,7 @@ Mimics the transformation offsets of the Vanilla RIGHT_LEG - #### `LEFT_LEG` \{#LEFT_LEG} -Mimics the transformation offsets of the Vanilla LEFT_LEG +Mimics the transformation offsets of the Vanilla `LEFT_LEG` --- @@ -121,8 +123,9 @@ Mimics the transformation offsets of the Vanilla LEFT_LEG - #### `RightElytron` \{#RightElytron} - #### `RIGHT_ELYTRON` \{#RIGHT_ELYTRON} -Mimics the transformation offsets of the Vanilla RIGHT_ELYTRA
-ModelParts with this ParentType are only visible while an Elytra is equipped.
+Mimics the transformation offsets of the Vanilla `RIGHT_ELYTRA` + +ModelParts with this ParentType are only visible while an Elytra is equipped. --- @@ -132,8 +135,9 @@ ModelParts with this ParentType are only visible while an Elytra is equipped.
LEFT_ELYTRA
-ModelParts with this ParentType are only visible while an Elytra is equipped.
+Mimics the transformation offsets of the Vanilla `LEFT_ELYTRA` + +ModelParts with this ParentType are only visible while an Elytra is equipped. --- @@ -141,7 +145,8 @@ ModelParts with this ParentType are only visible while an Elytra is equipped.
CAPE
+Mimics the transformation offsets of the Vanilla `CAPE` + This ParentType works even if you don't own a vanilla Cape. --- @@ -156,9 +161,12 @@ Special ParentTypes are ParentTypes that provide unique rendering functionality - #### `WORLD` \{#WORLD} -This ParentType will cause the ModelPart to be parented to the Minecraft World itself rather than your Player.
-Position (0,0,0) will be at the world's origin. 1 block is 16 ModelPart units, so multiply the world coordinates by 16 before setting the position of a World ParentType ModelPart.
-Rotation (0,0,0) will be facing South instead of what BlockBench defines as North.
+This ParentType will cause the ModelPart to be parented to the Minecraft World itself rather than your Player. + +Position (0,0,0) will be at the world's origin. 1 block is 16 ModelPart units, so multiply the world coordinates by 16 before setting the position of a World ParentType ModelPart. + +Rotation (0,0,0) will be facing South instead of what Blockbench defines as North. + ModelParts with this ParentType will be visible while in First Person. --- @@ -172,7 +180,8 @@ ModelParts with this ParentType will be visible while in First Person. - #### `GraphicalUserInterface` \{#GraphicalUserInterface} - #### `JraficalUserInterface` \{#JraficalUserInterface} -This ParentType causes the ModelPart to render on the Hud instead of on your player. This only affects the owner's Hud, or players that spectate the owner of the avatar.
+This ParentType causes the ModelPart to render on the Hud instead of on your player. This only affects the owner's Hud, or players that spectate the owner of the avatar. + (0,0,0) is the top left of the screen. 1 ModelPart unit is 1 Minecraft Gui unit. -X moves the ModelPart Right on the screen, and -Y moves the ModelPart Down on the screen. The Z axis determines which ModelParts render on top of others, with -Z moving the ModelPart closer. You can even have ModelParts render on top of the vanilla GUI. --- @@ -200,8 +209,9 @@ This ParentType causes the ModelPart to replace the Vanilla Skull. - #### `PORTRAIT` \{#PORTRAIT} -This ParentType will change the player icon in the TAB LIST.
-Blockbench 0, 0, 0 is the bottom center and the valid area extends 4 units horizontally on each since and 8 units up.
+This ParentType will change the player icon in the TAB LIST. + +Blockbench 0, 0, 0 is the bottom center and the valid area extends 4 units horizontally on each since and 8 units up. --- @@ -209,8 +219,9 @@ Blockbench 0, 0, 0 is the bottom center and the valid area extends 4 units horiz - #### `ARROW` \{#ARROW} -This ParentType replaces the model of arrows fired by you. The pivot point of the ModelPart that has this ParentType does not matter.
-(0,0,0) in BlockBench is the point on the vanilla arrow's shaft that is just before the arrow head. +This ParentType replaces the model of arrows fired by you. The pivot point of the ModelPart that has this ParentType does not matter. + +(0,0,0) in Blockbench is the point on the vanilla arrow's shaft that is just before the arrow head. --- @@ -224,7 +235,7 @@ This ParentType designates a Custom Item Model that can be used in the ITEM_REND ## Pivot Types -Pivot ParentTypes move the location of specific Vanilla Parts to the pivot point of the ModelPart. If multiple of the same Pivot ParentType are in a bbmodel, multiple of them are rendered. These ParentTypes will only render their Vanilla Part if the part in the vanilla_model global is visible. +Pivot ParentTypes move the location of specific Vanilla Parts to the pivot point of the ModelPart. If multiple of the same Pivot ParentType are in a bbmodel, multiple of them are rendered. These ParentTypes will only render their Vanilla Part if the part in the `vanilla_model` global is visible. --- diff --git a/docs/enums/PlayStates.md b/docs/enums/PlayStates.md index bc774c7c..9398920d 100644 --- a/docs/enums/PlayStates.md +++ b/docs/enums/PlayStates.md @@ -1,4 +1,4 @@ -The play state of a Blockbench animation, detected with getPlayState(). +The play state of a Blockbench animation, detected with `getPlayState()`. **Example**: diff --git a/docs/enums/PlayerModelParts.md b/docs/enums/PlayerModelParts.md index 6d49cf45..beae50bf 100644 --- a/docs/enums/PlayerModelParts.md +++ b/docs/enums/PlayerModelParts.md @@ -1,4 +1,4 @@ -These are outer layer parts used in conjunction with player:isSkinLayerVisible(String) to detect what parts a player has enabled via the Minecraft Skin Customizations setting. +These are outer layer parts used in conjunction with `player:isSkinLayerVisible(String)` to detect what parts a player has enabled via the Minecraft Skin Customizations setting. **Example:** diff --git a/docs/enums/PostEffects.md b/docs/enums/PostEffects.md index 0d6a9028..5bf9a9fd 100644 --- a/docs/enums/PostEffects.md +++ b/docs/enums/PostEffects.md @@ -1,4 +1,4 @@ -These are the Super Secret Settings screen effects. They can be applied to the avatar user's POV via renderer:setPostEffect(string). +These are the Super Secret Settings screen effects. They can be applied to the avatar user's POV via `renderer:setPostEffect(string)`. For more information, consult the [wiki](https://minecraft.wiki/w/Shaders/Before_1.9). **Example**: diff --git a/docs/enums/RenderTypes.md b/docs/enums/RenderTypes.md index ed01f5d8..726ced29 100644 --- a/docs/enums/RenderTypes.md +++ b/docs/enums/RenderTypes.md @@ -1,4 +1,4 @@ -Modelpart render types that can be applied via setPrimaryRenderType(string) or setSecondaryRenderType(string) +Modelpart render types that can be applied via `setPrimaryRenderType(string)` or `setSecondaryRenderType(string)` There can only be one primary and secondary type applied to a cube at once, so you may get unwanted behavior if you make the primary render type `LINES` as all the pixels aside from the lines will vanish. diff --git a/docs/enums/TextureTypes.md b/docs/enums/TextureTypes.md index ef3429e3..4a2db557 100644 --- a/docs/enums/TextureTypes.md +++ b/docs/enums/TextureTypes.md @@ -1,4 +1,4 @@ -Texture Types you can set using setPrimaryTexture and setSecondaryTexture
+Texture Types you can set using `setPrimaryTexture` and `setSecondaryTexture` **Example**: diff --git a/docs/globals/Animations/Animation.md b/docs/globals/Animations/Animation.md index d9ec55ed..6b3c41bc 100644 --- a/docs/globals/Animations/Animation.md +++ b/docs/globals/Animations/Animation.md @@ -120,7 +120,7 @@ myAnim:isPaused() Get the animation's playback state -These will either be `"PLAYING"`, `"STOPPED"`, or `"PAUSED"` +These will either be `PLAYING`, `STOPPED`, or `PAUSED` **Example**: diff --git a/docs/globals/Events/Events.md b/docs/globals/Events/Events.md index bd63a244..5df79439 100644 --- a/docs/globals/Events/Events.md +++ b/docs/globals/Events/Events.md @@ -284,7 +284,11 @@ If returned true, the event cancels its vanilla function Calling the player without a player:isLoaded() check will error here. -Note: This event is several ticks slower than its alternative function in the [player API](../globals/Player#isusingitem): player:isUsingItem() +:::tip + +This event is several ticks slower than its alternative function in the [player API](../globals/Player#isusingitem), player:isUsingItem(). + +::: ```lua function events.use_item(item, action, particles) diff --git a/docs/globals/Host/Host.md b/docs/globals/Host/Host.md index 09ddaf6b..76a56360 100644 --- a/docs/globals/Host/Host.md +++ b/docs/globals/Host/Host.md @@ -1,4 +1,4 @@ -The host API is accessed through the host global. Like so: host:isFlying() +The host API is accessed through the `host` global. Like so: `host:isFlying()` Functions in the host API aren't synced, meaning to be useful in multiplayer their information will need to be synced via [pings](../tutorials/Pings). @@ -74,7 +74,7 @@ Gets an ItemStack for the item in the given slot The slot is either their numerical id (0 indexed) or the slot string, as used in the /item command -For the numerical id, 0-8 are the hotbar, 9-35 are the rest of the inventory starting from the top left slot, 99 is the offhand, and 100-103 are the armor slots from the boots to the helmet. player:getItem() is a better alternative for getting equipment slots. +For the numerical id, 0-8 are the hotbar, 9-35 are the rest of the inventory starting from the top left slot, 99 is the offhand, and 100-103 are the armor slots from the boots to the helmet. `player:getItem()` is a better alternative for getting equipment slots. **Example**: @@ -151,7 +151,7 @@ host:getScreen() Returns a table of all of the player's status effects -The table contains sub-tables, each of which contains the name, amplifier, duration, and particle visibility of each status effect. To access a sub table index the effect table with the sub-table's name. Re the example below: effect.name +The table contains sub-tables, each of which contains the name, amplifier, duration, and particle visibility of each status effect. To access a sub table index the effect table with the sub-table's name. Re the example below: `effect.name` **Example**: diff --git a/docs/globals/Keybinds/Keybinds.md b/docs/globals/Keybinds/Keybinds.md index 50470d85..0baef587 100644 --- a/docs/globals/Keybinds/Keybinds.md +++ b/docs/globals/Keybinds/Keybinds.md @@ -10,7 +10,7 @@ The name is used in the keybind menu The key parameter is an identifier for a key, such as "key.keyboard.r" -The boolean gui indicates whether the keybind should always work, or if it should only work when you don't have a screen open +The boolean GUI indicates whether the keybind should always work, or if it should only work when you don't have a screen open Check the docs enum command for all key names diff --git a/docs/globals/Models/Models.md b/docs/globals/Models/Models.md index 20a7f2f5..8c22d7e5 100644 --- a/docs/globals/Models/Models.md +++ b/docs/globals/Models/Models.md @@ -50,7 +50,7 @@ models:setRot(0, 90, 0) ### getRot() \{#getRot} -Gets the rotation of the model part, including its rotation in blockbench +Gets the rotation of the model part, including its rotation in Blockbench For relative rotation values, check out the "offset" rot functions @@ -64,7 +64,7 @@ models:setRot() ### setPos(Vector3) \{#setPos} -Sets the position offset for this part from its blockbench position +Sets the position offset for this part from its Blockbench position Nil values for position are assumed to be 0 @@ -78,7 +78,7 @@ models:setPos(0, 5, 0) ### getPos() \{#getPos} -Gets the position of the model part, as an offset from its position in blockbench +Gets the position of the model part, as an offset from its position in Blockbench Only changes from {0,0,0} when you call setPos() @@ -106,7 +106,7 @@ models:setScale(2, 2, 2) ### getScale() \{#getScale} -Gets the scale of the model part, as a multiple of its blockbench size +Gets the scale of the model part, as a multiple of its Blockbench size Only changes from {1,1,1} when you call setScale() @@ -136,7 +136,7 @@ models:setPivot(0, 5, 0) ### getPivot() \{#getPivot} -Gets the pivot point of the model part, including its pivot in blockbench +Gets the pivot point of the model part, including its pivot in Blockbench For relative values, check out the "offset" pivot functions @@ -168,7 +168,7 @@ models:setOffsetRot(0, 90, 0) ### getOffsetRot() \{#getOffsetRot} -Gets the offset rotation of the model part, offset from its rotation in blockbench +Gets the offset rotation of the model part, offset from its rotation in Blockbench For absolute rotation values, check out the non-offset rot functions @@ -228,7 +228,7 @@ models:setOffsetPivot(0, 5, 0) ### getOffsetPivot() \{#getOffsetPivot} -Gets the offset pivot of the model part, offset from its pivot in blockbench +Gets the offset pivot of the model part, offset from its pivot in Blockbench For absolute pivot point values, check out the non-offset pivot functions diff --git a/docs/globals/Nameplate/EntityNameplateCustomization.md b/docs/globals/Nameplate/EntityNameplateCustomization.md index 1e5409d1..02dc54c7 100644 --- a/docs/globals/Nameplate/EntityNameplateCustomization.md +++ b/docs/globals/Nameplate/EntityNameplateCustomization.md @@ -12,7 +12,7 @@ nameplate.Entity:setText("Hi") ### getText() \{#getText} -Gets the text of the nameplate as set by setText +Gets the text of the nameplate as set by `setText` ```lua nameplate.Entity:getText() @@ -112,7 +112,7 @@ nameplate.Entity:setLight(15, 15) ### getLight() \{#getLight} -Gets the brightness of the nameplate text as set by setLight +Gets the brightness of the nameplate text as set by `setLight` ```lua nameplate.Entity:getLight() @@ -122,7 +122,7 @@ nameplate.Entity:getLight() ### setOutline(bool) \{#setOutline} -Sets if the nameplate text should be outlined. Incompatible with setShadow +Sets if the nameplate text should be outlined. Incompatible with `setShadow` ```lua nameplate.Entity:setOutline(true) @@ -162,7 +162,7 @@ nameplate.Entity:setBackgroundColor(100 / 255, 100 / 255, 100 / 255) ### getBackgroundColor() \{#getBackgroundColor} -Gets the color of the nameplate background as set by setBackgroundColor +Gets the color of the nameplate background as set by `setBackgroundColor` ```lua nameplate.Entity:getBackgroundColor() diff --git a/docs/globals/Player/Entity.md b/docs/globals/Player/Entity.md index 556dd2be..2ddf0d06 100644 --- a/docs/globals/Player/Entity.md +++ b/docs/globals/Player/Entity.md @@ -352,7 +352,7 @@ Returns a proxy for the entity that this entity is currently riding If the entity isn't riding anything, returns nil -**Example** combined with getType and with a nil check, the first thisEntity:getVehicle() is preventing a nil value from being check by getType() after the and: +**Example** combined with getType and with a nil check, the first `thisEntity:getVehicle()` is preventing a nil value from being check by `getType()` after the and: ```lua if thisEntity:getVehicle() and thisEntity:getVehicle():getType() == "minecraft:pig" then @@ -408,7 +408,10 @@ thisEntity:getBoundingBox() Returns whether or not this entity is currently on the ground -:::caution Due to a glitch in Minecraft's code this function is unreliable, and will misfire in multiple situations such as being underwater, standing on a boat, or standing on a slime block. One workaround is to check the blockstate of the block directly underneath the entity like so: world.getBlockState(thisEntity:getPos():add(0,-0.1,0)):isSolidBlock() +:::caution + +Due to a glitch in Minecraft's code, this function is unreliable and will misfire in multiple situations, such as being underwater, standing on a boat, or standing on a slime block. One workaround is to check the block state of the block directly underneath the entity, like so: `world.getBlockState(thisEntity:getPos():add(0,-0.1,0)):isSolidBlock()` + ::: **Example**: diff --git a/docs/globals/Player/LivingEntity.md b/docs/globals/Player/LivingEntity.md index b9c1f708..b5f004da 100644 --- a/docs/globals/Player/LivingEntity.md +++ b/docs/globals/Player/LivingEntity.md @@ -542,7 +542,7 @@ Returns a proxy for the entity that this entity is currently riding If the entity isn't riding anything, returns nil -**Example** combined with getType and with a nil check, the first thisEntity:getVehicle() is preventing a nil value from being check by getType() after the and: +**Example** combined with getType and with a nil check, the first `thisEntity:getVehicle()` is preventing a nil value from being check by `getType()` after the and: ```lua if thisEntity:getVehicle() and thisEntity:getVehicle():getType() == "minecraft:pig" then @@ -598,7 +598,10 @@ thisEntity:getBoundingBox() Returns whether or not this entity is currently on the ground -:::caution Due to a glitch in Minecraft's code this function is unreliable, and will misfire in multiple situations such as being underwater, standing on a boat, or standing on a slime block. One workaround is to check the blockstate of the block directly underneath the entity like so: world.getBlockState(thisEntity:getPos():add(0,-0.1,0)):isSolidBlock() +:::caution + +Due to a glitch in Minecraft's code, this function is unreliable and will misfire in multiple situations, such as being underwater, standing on a boat, or standing on a slime block. One workaround is to check the block state of the block directly underneath the entity, like so: `world.getBlockState(thisEntity:getPos():add(0,-0.1,0)):isSolidBlock()` + ::: **Example**: diff --git a/docs/globals/Player/Player.md b/docs/globals/Player/Player.md index 508924fa..34c20faf 100644 --- a/docs/globals/Player/Player.md +++ b/docs/globals/Player/Player.md @@ -1,12 +1,16 @@ The player API inherits functions from the [living entity API](../globals/Player/LivingEntity) -The player API is accessed through the player global. Like so: player:isGliding() +The player API is accessed through the `player` global. Like so: `player:isGliding()` Player information that isn't synced between clients is kept in the host API. Examples of unsynced data are: Creative flying, status effects, and remaining air amount. -**_Note:_** There are times during a script's functioning where the script will run, but the player global will be empty. This will cause the "Tried to access the EntityAPI before its initialization" error. To solve this, move the player API call into a protected event. If you wish to initialize a check during the initialization phase of a script (outside of any other event) you can use the entity_init event. +:::warning -For most other circumstances you will want the tick event, as checks like player:isGliding() will be updated once a game tick inside that event. (There are 20 ticks in a second, and this is how often Minecraft updates information- some player functions work better in a tick event for this reason). +There are times during a script's functioning where the script will run, but the player global will be empty. This will cause the "Tried to access the EntityAPI before its initialization" error. To solve this, move the player API call into a protected event. If you wish to initialize a check during the initialization phase of a script (outside any other event) you can use the `entity_init` event. + +::: + +For most other circumstances you will want the `tick` event, as checks like `player:isGliding()` will be updated once a game tick inside that event. (There are 20 ticks in a second, and this is how often Minecraft updates information- some player functions work better in a tick event for this reason). All provided examples assume you're using a tick event. @@ -690,7 +694,7 @@ Returns a proxy for the entity that this player is currently riding If the player isn't riding anything, returns nil -**Example** combined with getType and with a nil check, the first player:getVehicle() is preventing a nil value from being check by getType() after the and: +**Example** combined with getType and with a nil check, the first `player:getVehicle()` is preventing a nil value from being check by `getType()` after the and: ```lua if player:getVehicle() and player:getVehicle():getType() == "minecraft:pig" then @@ -746,7 +750,10 @@ player:getBoundingBox() Returns whether or not this entity is currently on the ground -:::cation Due to a glitch in Minecraft's code this function is unreliable, and will misfire in multiple situations such as being underwater, standing on a boat, or standing on a slime block. One workaround is to check the blockstate of the block directly underneath the player like so: world.getBlockState(player:getPos():add(0,-0.1,0)):isSolidBlock() +:::caution + +Due to a glitch in Minecraft's code, this function is unreliable and will misfire in multiple situations, such as being underwater, standing on a boat, or standing on a slime block. One workaround is to check the block state of the block directly underneath the entity, like so: `world.getBlockState(player:getPos():add(0,-0.1,0)):isSolidBlock()` + ::: **Example**: diff --git a/docs/globals/Renderer/Renderer.md b/docs/globals/Renderer/Renderer.md index 1e505d89..ad0b7720 100644 --- a/docs/globals/Renderer/Renderer.md +++ b/docs/globals/Renderer/Renderer.md @@ -1,4 +1,4 @@ -The renderer API is accessed with the renderer global. Like so: renderer:setRenderVehicle(false) +The renderer API is accessed with the `renderer` global. Like so: `renderer:setRenderVehicle(false)` ## Altering the Camera diff --git a/docs/globals/Sounds/Sound.md b/docs/globals/Sounds/Sound.md index aba6378e..ebfde41b 100644 --- a/docs/globals/Sounds/Sound.md +++ b/docs/globals/Sounds/Sound.md @@ -62,7 +62,7 @@ mySound:setPos(player:getPos()) ### `getPos()` \{#getPos} -Gets the position of the sound as set by setPos +Gets the position of the sound as set by `setPos` **Example**: diff --git a/docs/globals/World/World.md b/docs/globals/World/World.md index a9f9361a..f149b4da 100644 --- a/docs/globals/World/World.md +++ b/docs/globals/World/World.md @@ -1,4 +1,4 @@ -The world API is accessed through the world global. Like so: world.getTime(). +The world API is accessed through the `world` global. Like so: `world.getTime()`. :::info The functions in the World API never receive `self` as a parameter. Because of this they should be called with a `.` instead of `:` @@ -273,7 +273,11 @@ Parses and create a new ItemStack from the given string A count and damage can be given, to be applied on this itemstack -Note: This doesn't create an item in the world, if you want to make a fake item you want [item tasks](../globals/Models/ItemTask) +:::note + +This doesn't create an item in the world. If you want to make a fake item, use [item tasks](../globals/Models/ItemTask) + +::: **Example**: @@ -289,7 +293,11 @@ Parses and create a new BlockState from the given string A world position can be optionally given for the blockstate functions that relies on its position -Note: This doesn't create a block in the world, if you want to make a fake block you want [block tasks](../globals/Models/BlockTask) +:::note + +This doesn't create a block in the world. If you want to make a fake block, use [block tasks](../globals/Models/BlockTask) + +::: **Example**: diff --git a/docs/globals/misc/require.md b/docs/globals/misc/require.md index ee2bbafd..81d743e9 100644 --- a/docs/globals/misc/require.md +++ b/docs/globals/misc/require.md @@ -14,7 +14,7 @@ If the name you give isn't any of your scripts, it will error ### Examples -#### Script in root folder +#### Script in Root Folder @@ -28,7 +28,7 @@ If the name you give isn't any of your scripts, it will error require("JimmyAnims") ``` -#### Script in another folder +#### Script in Another Folder diff --git a/docs/start_here/Avatar File Format.md b/docs/start_here/Avatar File Format.md index f6be69f6..1e2edf9d 100644 --- a/docs/start_here/Avatar File Format.md +++ b/docs/start_here/Avatar File Format.md @@ -2,36 +2,37 @@ import Emoji from '@site/src/components/Emoji'; import FileTreeRoot from '@site/src/components/FileTree/Root'; import FileTreeNode from '@site/src/components/FileTree/Node'; -Avatars are stored in <minecraftDirectory>/figura/avatars. You can get to this folder quickly via the button in the Figura Menu.
-A Figura Avatar consists of a named folder or a zip file containing an avatar.json file. That is everything needed for an avatar to appear in Wardrobe.
+Avatars are stored in `/figura/avatars`. You can get to this folder quickly via the button in the Figura Menu. + +A Figura Avatar consists of a named folder or a zip file containing an `avatar.json` file. That is everything needed for an avatar to appear in Wardrobe. - + -An avatar.json file is just a renamed text file which contains [Avatar Metadata](../tutorials/Avatar%20Metadata) in the form of a json object, but it can be empty. It's presence tells Figura that this folder is an Avatar. +An `avatar.json` file is just a renamed text file which contains [Avatar Metadata](../tutorials/Avatar%20Metadata) in the form of a json object, but it can be empty. It's presence tells Figura that this folder is an Avatar. -Figura also looks for an image named avatar.png. This will be used as the avatar's icon which will appear next to it's name in the Wardrobe. +Figura also looks for an image named `avatar.png`. This will be used as the avatar's icon which will appear next to it's name in the Wardrobe. - + -Additional files go either in the same folder as the avatar.json, or within a subfolder. +Additional files go either in the same folder as the `avatar.json`, or within a subfolder. -- All files with the extension .lua will be treated as script files and executed when your avatar is loaded. -- All files with the extension .bbmodel will be treated as model files. The minimum BlockBench version supported is 4.0. -- All files with the extension .ogg will be treated as sound files. They must be in Vorbis codec. +- All files with the extension `.lua` will be treated as script files and executed when your avatar is loaded. +- All files with the extension `.bbmodel` will be treated as model files. The minimum Blockbench version supported is `4.0`. +- All files with the extension `.ogg` will be treated as sound files. They must be in Vorbis codec. Stray texture files in the avatar folder will not be loaded by Figura. For a texture to be loaded by Figura, it must be registered as a texture in a bbmodel file. -_ALL_ files that begin with a period (.) will be ignored when figura loads an avatar. Files that are not loaded by Figura are not accessible at all, so don't bother trying to get around the 100kb limit with this. +_ALL_ files that begin with a period (`.`) will be ignored when Figura loads an avatar. Files that are not loaded by Figura are not accessible at all, so don't bother trying to get around the 100kb limit with this. diff --git a/docs/start_here/BlockBench.md b/docs/start_here/BlockBench.md index e31d0ece..fcfe6ab4 100644 --- a/docs/start_here/BlockBench.md +++ b/docs/start_here/BlockBench.md @@ -1,41 +1,47 @@ import Emoji from '@site/src/components/Emoji'; +import Image from '@site/src/components/Image'; -Proper tutorials for blockbench can be found online. This page just explains Figura specific stuff. This page assumes you are using the Desktop version of BlockBench, not the online app.
+Proper tutorials for Blockbench can be found online. This page just explains Figura specific stuff. This page assumes you are using the Desktop version of Blockbench, not the online app. ## Project Properties -This is the popup that appears when you create a Project. You can also get to this page via File->Project.
-
-Figura only accepts bbmodels in the Generic Model format. If your format is not Generic Model, Figura will refuse to load the avatar. To convert a project, File->Convert Project. Deselect Create Copy, ensure format is Generic Model, and press Confirm. If the popup does not go away after pressing Confirm, close it manually.
-
+This is the popup that appears when you create a Project. You can also get to this page via File->Project. -The File Name and Model Identifier fields are unused by Figura.
-UV Mode determines how BlockBench handles how UVs are positioned. Figura will handle both Box UV and Per-face UV. Its up to you which you want. UVs determine where a 2D texture is applied to a 3D model. Each face has it's own UV coordinates which determines where on the 2D texture it will get it's pixels from.

+ - -Box UV forces each face of a cube to match how vanilla does UVs. If you have ever edited your own vanilla skin before, you will recognize the pattern. While this does simplify the texturing process, it limits what you can do. Also, all textures in the model must have the same size, as what is a pixel is determined by the project's global Texture Size instead of the size of the texture itself. Also, meshes cannot be used while using Box UV
+Figura only accepts bbmodels in the Generic Model format. If your format is not Generic Model, Figura will refuse to load the avatar. To convert a project, File->Convert Project. Deselect `Create Copy`, ensure format is Generic Model, and press Confirm. If the popup does not go away after pressing Confirm, close it manually. -
+ - +The `File Name` and `Model Identifier` fields are unused by Figura. -Per-face UV allows full control over each face of the cube/mesh. Each face can be positioned, scaled, and rotated individually from each other. You can even set a different texture for each face, or remove a face to reduce clutter. While the pixel grid is effected by the project's global Texture Size, changing the Texture Size has zero effect on the UVs themselves, unlike Box UV which will have destructive effects when changing the project +`UV Mode` determines how Blockbench handles how UVs are positioned. Figura will handle both `Box UV` and `Per-face UV`. Its up to you which you want. UVs determine where a 2D texture is applied to a 3D model. Each face has it's own UV coordinates which determines where on the 2D texture it will get it's pixels from. -
+ -Texture Size.
+`Box UV` forces each face of a cube to match how vanilla does UVs. If you have ever edited your own vanilla skin before, you will recognize the pattern. While this does simplify the texturing process, it limits what you can do. Also, all textures in the model must have the same size, as what is a pixel is determined by the project's global `Texture Size` instead of the size of the texture itself. Also, meshes cannot be used while using `Box UV` -The Texture Size field aids with UV calculation. In rendering, UVs are a float from 0-1 representing the percentage of the texture that this point is at. A UV of (0.5,0.5) represents the center of the texture, regardless of the texture's own size. A way of calculating this percentage is to take the pixel coordinate you want and divide it by the texture's size. (32,16)/(64,64)=(0.5,0.25). The Texture Size field determines this texture size globally. BlockBench never uses the texture's actual size, which causes issues when you have a model with textures of different sizes. Thankfully, changing it only has an effect om ModelParts that use Box UV, so when you need to edit ModelParts using a different sized texture, you can change this with no worries so long as you are using Per-face UV.
+
+ + + +`Per-face UV` allows full control over each face of the cube/mesh. Each face can be positioned, scaled, and rotated individually from each other. You can even set a different texture for each face, or remove a face to reduce clutter. While the pixel grid is effected by the project's global `Texture Size`, changing the `Texture Size` has zero effect on the UVs themselves, unlike `Box UV` which will have destructive effects when changing the project + +
+ +`Texture Size`. + +The `Texture Size` field aids with UV calculation. In rendering, UVs are a float from 0-1 representing the percentage of the texture that this point is at. A UV of (0.5,0.5) represents the center of the texture, regardless of the texture's own size. A way of calculating this percentage is to take the pixel coordinate you want and divide it by the texture's size. (32,16)/(64,64)=(0.5,0.25). The `Texture Size` field determines this texture size globally. Blockbench never uses the texture's actual size, which causes issues when you have a model with textures of different sizes. Thankfully, changing it only has an effect om ModelParts that use `Box UV`, so when you need to edit ModelParts using a different sized texture, you can change this with no worries so long as you are using `Per-face UV`. ## ModelParts ### ParentTypes -If the name of a group begins with a specific string, Figura will apply special effects to that group. Some examples include "Head", "RightArm", "World". These are called [ParentTypes](../enums/ModelPartParentTypes). +If the name of a group begins with a specific string, Figura will apply special effects to that group. Some examples include `Head`, `RightArm`, `World`. These are called [ParentTypes](../enums/ModelPartParentTypes). -### Blank Texture +### `Blank` Texture -ModelParts that use the BlockBench inbuilt Blank texture will not be loaded by Figura at all. If you want a Model to not have a texture and assign the texture via script, use the [ignoredTextures metadata customization](../tutorials/Avatar%20Metadata). The Transparent texture that can only be applied to individual faces in Per-face UV behave the same way. Figura will not load those faces. +ModelParts that use the Blockbench inbuilt `Blank` texture will not be loaded by Figura at all. If you want a Model to not have a texture and assign the texture via script, use the [`ignoredTextures` metadata customization](../tutorials/Avatar%20Metadata). The `Transparent` texture that can only be applied to individual faces in Per-face UV behave the same way. Figura will not load those faces. ### Meshes @@ -45,79 +51,87 @@ ModelParts that use the BlockBench inbuilt Blank texture will not b ### Local/External Textures -In BlockBench, textures have 2 distinct states: Local and External.
-To determine the state your texture is in, Right Click a texture->Properties. An External texture will have a file path, while a Local one will not.
There is one key factor for a texture to be External, and that is for the file itself to be inside the avatar's folder. If the filepath does not lead to a file inside the avatar's folder, Figura will load it as a Local file.
-
+In Blockbench, textures have 2 distinct states: local and external. + +To determine the state your texture is in, Right Click a texture->Properties. An External texture will have a file path, while a Local one will not. + +There is one key factor for a texture to be External, and that is for the file itself to be inside the avatar's folder. If the filepath does not lead to a file inside the avatar's folder, Figura will load it as a local file. -Whether a texture is Local or External will determine how Figura will load it which is important when getting a Texture in script.
+ -The Render Mode field determines how the texture will be rendered. In BlockBench, this changes nothing visually.
-**Figura ignores Render Mode.** The Primary Texture will always be "TRANSLUCENT" by default, and the Secondary Texture will always be "EMISSIVE" by default.
+ -The Render Sides field determines if the cube should be rendered when looking at the back of a face.
-**Figura ignores Render Sides.** To apply the same effect, use the "TRANSLUCENT_CULL" [RenderType](../enums/RenderTypes) in a script.
+Whether a texture is Local or External will determine how Figura will load it which is important when getting a Texture in script. + +The `Render Mode` field determines how the texture will be rendered. In Blockbench, this changes nothing visually. + +**Figura ignores `Render Mode`.** The Primary Texture will always be `TRANSLUCENT` by default, and the Secondary Texture will always be `EMISSIVE` by default. + +The `Render Sides` field determines if the cube should be rendered when looking at the back of a face. + +**Figura ignores `Render Sides`.** To apply the same effect, use the `TRANSLUCENT_CULL` [RenderType](../enums/RenderTypes) in a script. ### Texture Suffix -In BlockBench, each cube (face) can only point to a single texture, which means that Figura needs to get creative when it wants to link multiple textures together for stuff like emissive textures.
-When Figura loads a texture, it looks for another texture with the same name but with a specific suffix. Then for all ModelParts in BlockBench that use the texture, Figura will link the suffixed texture to that ModelPart as well. +In Blockbench, each cube (face) can only point to a single texture, which means that Figura needs to get creative when it wants to link multiple textures together for stuff like emissive textures. + +When Figura loads a texture, it looks for another texture with the same name but with a specific suffix. Then for all ModelParts in Blockbench that use the texture, Figura will link the suffixed texture to that ModelPart as well. List of suffixes used by Figura: -- \_e: This texture will be used as the Secondary Texture, also known as the [Emissive Texture](../tutorials/Emissive%20Textures), of the ModelPart. The Secondary RenderType of a ModelPart is by default "EMISSIVE", but can be changed in script. -- \_n: This texture will be used as the [Normal Texture](https://en.wikipedia.org/wiki/Normal_mapping). Do not confuse this with the Primary Texture. "Normal" means something very specific in modeling. This suffix is used with Iris Shaders, and does nothing with vanilla rendering. This suffix currently does not function. -- \_s: This texture will be used as the [Specular Texture](https://en.wikipedia.org/wiki/Specularity). This suffix is used with Iris Shaders, and does nothing with vanilla rendering. This suffix currently does not function. +- `\_e`: This texture will be used as the Secondary Texture, also known as the [Emissive Texture](../tutorials/Emissive%20Textures), of the ModelPart. The Secondary RenderType of a ModelPart is by default `EMISSIVE`, but can be changed in script. +- `\_n`: This texture will be used as the [Normal Texture](https://en.wikipedia.org/wiki/Normal_mapping). **Do not confuse this with the Primary Texture**. "Normal" means something very specific in modeling. This suffix is used with Iris Shaders, and does nothing with vanilla rendering. **_This suffix currently does not function_**. +- `\_s`: This texture will be used as the [Specular Texture](https://en.wikipedia.org/wiki/Specularity). This suffix is used with Iris Shaders, and does nothing with vanilla rendering. **_This suffix currently does not function_**. + +An example is the `Head`, `skin`, and `skin_e`. When the `Head` uses the texture `skin`, when the Avatar is loaded, `skin_e` is used as the Secondary Texture, ie the Emissive Texture. -An example is the Head, skin, and skin_e. When the Head uses the texture skin, when the Avatar is loaded, skin_e is used as the Secondary Texture, ie the Emissive Texture.
-
+ -For a texture to have the same name, they must both be either [Local or External](#localexternal-textures), and should they be external, they must be in the same folder. Otherwise, they will not have the same name internally.
-For textures with file extensions, the suffix goes before the extension. skin_e.png
+For a texture to have the same name, they must both be either [Local or External](#localexternal-textures), and should they be external, they must be in the same folder. Otherwise, they will not have the same name internally. + +For textures with file extensions, the suffix goes before the extension. `skin_e.png` ## Animations ### Animation Properties -This popup appears when you create an animation. To get back to this popup, Right Click an Animation->Properties.
+This popup appears when you create an animation. To get back to this popup, Right Click an Animation->Properties. + + -
+`Name` is the animation's name. It is very important that you change this to something shorter. The entire textbox is the animation's name, so unless you want to refer to this animation in lua with `animations.player["animation.model.new"]`, change the name. An animation named just `new` is indexed via `animations.player.new`. Much nicer, right? -Name is the animation's name. It is very important that you change this to something shorter. The entire textbox is the animation's name, so unless you want to refer to this animation in lua with animations.player["animation.model.new"], change the name. An animation named just "new" is indexed via animations.player.new. Much nicer, right? -

+`Loop Mode` controls what happens when the animation stops. There are 3 valid loop modes: Play Once, Hold On Last Frame, and Loop. -Loop Mode controls what happens when the animation stops. There are 3 valid loop modes: Play Once, Hold On Last Frame, and Loop.
-Play Once stops the animation once the animation ends.
-Hold On Last Frame keeps the animation values from the end of the animation. The animation is still technically playing.
-Loop sets the animation's time to 0, or to the animation's end if the animation is playing backwards. -

+- Play Once: Stops the animation once the animation ends. +- Hold On: Last Frame keeps the animation values from the end of the animation. The animation is still technically playing. +- Loop: Sets the animation's time to 0, or to the animation's end if the animation is playing backwards. -Override determines if Mimic-type ParentTypes will apply their transformations while this animation is playing. It only effects ModelParts that have a keyframe in this animation. Default false -

+`Override` determines if Mimic-type [ParentTypes](../enums/ModelPartParentTypes) will apply their transformations while this animation is playing. It only effects ModelParts that have a keyframe in this animation. Default `false` -Snapping determines the snapping distance for keyframes. Holding ctrl while moving a keyframe ignores this. Figura does not care about this value. -

+`Snapping` determines the snapping distance for keyframes. Holding ctrl while moving a keyframe ignores this. **Figura does not care about this value**. -Anim Time Update. I have no clue what this does in blockbench, but figura uses this value for determining the start offset. In other words, when you call play this is the time that figura will start the animation at. This allows you to put keyframes behind the start of the animation which can help with Cubic Interpolation keyframes. Default is 0. -

+`Anim Time Update`. I have no clue what this does in Blockbench, but Figura uses this value for determining the start offset. In other words, when you call `play` this is the time that figura will start the animation at. This allows you to put keyframes behind the start of the animation which can help with Cubic Interpolation keyframes. Default is `0`. -Blend Weight is a multiplier for every single keyframe in the animation. Not very useful as a property, but it can be changed in script to raise or reduce the intensity of animations. Default is 1. -

+`Blend Weight` is a multiplier for every single keyframe in the animation. Not very useful as a property, but it can be changed in script to raise or reduce the intensity of animations. Default is `1`. -Start Delay is the time it takes after calling play for the animation to actually start. Default is 0. -

+`Start Delay` is the time it takes after calling `play` for the animation to actually start. Default is `0`. -Loop Delay is a property that only shows up with the Loop Loop Mode. It adds a delay between the animation ending, then starting again. Default is 0. -

+`Loop Delay` is a property that only shows up with the Loop `Loop Mode`. It adds a delay between the animation ending, then starting again. Default is `0`. ### Keyframe Expressions -While blockbench supports Molang, **Figura does not**.
-To remedy this, Figura allows writing lua code into keyframe fields.
+While Blockbench supports Molang, **Figura does not**. + +To remedy this, Figura allows writing lua code into keyframe fields. Figura provides data for the keyframe expression, which is accessible via the `...` variable. -It has 2 pieces of data, the keyframe time, and the Animation object of the animation itself.
-Keyframe time is measured in percentage, not seconds. So assuming a Step interpolation keyframe, `0` is at the time at the keyframe itself, and `1` is at the next keyframe. Keyframe time is only useful when the keyframe uses Step interpolation.
When using other interpolation types, the expression will execute before it has reached the keyframe itself to interpolate. While this happens, it will give the Keyframe time of the previous keyframe and go back to zero once it reaches itself. +It has 2 pieces of data, the keyframe time, and the Animation object of the animation itself. + +Keyframe time is measured in percentage, not seconds. So assuming a step interpolation keyframe, `0` is at the time at the keyframe itself, and `1` is at the next keyframe. Keyframe time is only useful when the keyframe uses step interpolation. + +When using other interpolation types, the expression will execute before it has reached the keyframe itself to interpolate. While this happens, it will give the Keyframe time of the previous keyframe and go back to zero once it reaches itself. They can be extracted via the following line: @@ -130,37 +144,45 @@ Keyframe Expressions accept 2 different formats: - A single lua expression that evaluates to a number - A lua script that `returns` a number -`math.sin(world.getTime())` is a single lua expression, so it is a valid Keyframe Expression.
However, `local _, anim=... math.sin(anim:getTime())` is not a single lua expression and will need to have an explicit return value: +`math.sin(world.getTime())` is a single lua expression, so it is a valid Keyframe Expression. + +However, `local _, anim=... math.sin(anim:getTime())` is not a single lua expression and will need to have an explicit return value: ```lua local _, anim = ... return math.sin(anim:getTime()) ``` -Alternatively, you can rewrite it as a single lua expression: `math.sin({...}[2]:getTime())`
-This deconstructs the `...` varargs into a table and grabs the second value. +Alternatively, you can rewrite it as a single lua expression: `math.sin({...}[2]:getTime())`. This deconstructs the `...` varargs into a table and grabs the second value. ### Instruction Keyframes -Instruction Keyframes run lua code when the Animation reaches that keyframe. This can be used to play sounds, spawn particles, literally anything. Remember that Lua code is what goes in this spot, not Molang.
-You can access Instruction Keyframes via the Magic Wand icon. An Effects timeline should appear along with the other ModelPart timelines. +Instruction keyframes run lua code when the animation reaches that keyframe. This can be used to play sounds, spawn particles, literally anything. Remember that Lua code is what goes in this spot, not Molang. + +You can access instruction keyframes via the magic wand icon. An effects timeline should appear along with the other ModelPart timelines. -### Animation Features That Figura Does Not Care About +### Unsupported Animation Features -Below are features provided by BlockBench Animations that figura does not use when loading the bbmodel.
+Below are features provided by Blockbench Animations that Figura does not use when loading the bbmodel. -**Variable Placeholders**
-
-This is completely ignored by Figura.
+#### Variable Placeholders + + + +This is completely ignored by Figura. + +#### Inverse Kinematics -**Inverse Kinematics**
Don't bother. Not a thing in Figura. -**Global Rotation**
-There is a toggle for Global Rotation next to the Rotation timeline for ModelParts. Figura does not obey this, so keep it disabled.
+#### Global Rotation + +There is a toggle for Global Rotation next to the rotation timeline for ModelParts. Figura does not obey this, so keep it disabled. + +#### Sound Keyframes + +Figura does not read these. Use [Instruction Keyframes](#instruction-keyframes). -**Sound Keyframes**
-Figura does not read these. Use [Instruction Keyframes](#instruction-keyframes).
+#### Particle Keyframes -**Particle Keyframes**
-Figura does not read these. Use [Instruction Keyframes](#instruction-keyframes).
+Figura does not read these. Use [Instruction Keyframes](#instruction-keyframes). diff --git a/docs/tutorials/ActionWheel.md b/docs/tutorials/ActionWheel.md index 79f6918f..5c1bd75c 100644 --- a/docs/tutorials/ActionWheel.md +++ b/docs/tutorials/ActionWheel.md @@ -1,36 +1,36 @@ -The Action Wheel is a gui element provided by Figura that allows for adding highly customizable Actions that can provide additional functionality to your avatar. +The Action Wheel is a GUI element provided by Figura that allows for adding highly customizable actions that can provide additional functionality to your avatar. -The Action Wheel operates on Pages. Only a single Page can be active at a time.
-Pages contain Actions. A Page can have an unlimited amount of Actions, but the Action Wheel can only render 8 at a time. While a Page with more than 8 Actions is active, you can use the scroll wheel to move between the groups of 8 Actions within the Page. +The action wheel works with a system of pages, of which only one can be active at a time. -The docs page for the [Action Wheel](../globals/action-wheel) has more examples for specific action wheel functions +Each page can have an unlimited number of actions, but the action wheel can only render eight at a time. While a page with more than 8 actions is active, you can use the scroll wheel to move between the groups of 8 actions within the page. + +The documentation page for the [Action Wheel](../globals/action-wheel) has more examples for specific action wheel functions ## Example Action Wheel -First step is to create the Page that will hold the Actions. This is done via the newPage function. +The first step is to create the page that will hold the actions. This is done with the `newPage` function. ```lua local mainPage = action_wheel:newPage() ``` -This creates a new page, but thats it. If you save and try to open the Action Wheel (Default Keybind B), you will see a message stating that there is no active page. We can use the setPage function while providing a reference to a Page object to set the active page. +This creates a new page, but that's it. If you save and try to open the action wheel, bound to B by default, you will see a message stating that there is no active page. We can use the `setPage` function while providing a reference to a page object to set the active page. ```lua action_wheel:setPage(mainPage) ``` -Tada. New blank page and Figura isnt screaming at us. Now for some actions.
-You can call the newAction function on a Page object. This will create a new Action _and_ add it to the Page. +Tada. New blank page, and Figura isn't screaming at us. Now for some actions. You can call the `newAction` function on a page object. This will create a new Action _and_ add it to the page. -You technically do not need to store the Action in a variable. If you do, please give it a unique variable name. Using the same variable name for all actions can cause issues when doing more advanced stuff. +You technically do not need to store the action in a variable. If you do, please give it a unique variable name. Using the same variable name for all actions can cause issues when doing more advanced stuff. ```lua local action = mainPage:newAction() ``` -New Action, but it really doesn't look like much. Lets add a title, a display item, and perhaps change the color that appears when the Action is hovered over. +New action, but it really doesn't look like much. Let's add a title, a display item, and perhaps change the color that appears when the action is hovered over. -One thing to remember is that all Action functions return itself. This allows for functions to be chained together, always modifying the same action +One thing to remember is that all action functions return themselves. This allows functions to be chained together, always modifying the same action. ```lua @@ -40,7 +40,7 @@ local action = mainPage:newAction() :hoverColor(1, 0, 1) ``` -Pretty, but functionally useless. Lets add a function to the leftClick field. When the Action is left clicked, the function stored in the Action's leftClick field gets invoked. +Pretty, but functionally useless. Lets add a function to the `leftClick` field. When the Action is left clicked, the function stored in the Action's `leftClick` field gets invoked. ```lua @@ -48,22 +48,27 @@ local action = mainPage:newAction() :title("My Action") :item("minecraft:stick") :hoverColor(1, 0, 1) - -- the onLeftClick function just sets the Action's leftClick field + -- the onLeftClick function just sets the Action's leftClick field :onLeftClick(function() print("Hello World!") end) ``` -Now we have an Action that does stuff. You may not notice anything, but there is a glaring issue with the current code. +Now we have an action that does stuff. You may not notice anything, but there is a glaring issue with the current code. The issue is that the leftClick code will only execute on your computer. -As described in [Pings](./Pings), Figura is completely clientside. The Action Wheel is a feature added by Figura, meaning it will never be synced between clients via the Minecraft Server. So instead, we must use Pings that utilize Figura's Backend to sync data between clients. +As described in [pings](./Pings), Figura is completely client-side. The action wheel is a feature added by Figura, meaning it will never be synced between clients via the Minecraft server. Instead, we must use pings that utilize Figura's backend to sync data between clients. + +The first step is to take the code that would be executed on leftClick, and turn it into a ping function. Then, instead of assigning an anonymous function to `leftClick`, we assign the ping function itself to `leftClick` + +:::tip + +All ping functions must have unique names. -First step is to take the code that would be executed on leftClick, and turn it into a ping function. Then, instead of assigning an anonymous function to leftClick, we assign the ping function itself to leftClick +Ideally, they should also be named in a way that describes what they do to avoid confusion later on. Examples of good naming may include `pings.playEmote1` or `pings.setArmorVisibility`. -**_IMPORTANT: ALL PING FUNCTIONS MUST HAVE UNIQUE NAMES_**
-Also, please name your ping function so that it describes what it does. I _hate_ seeing pings.actionClicked in the hellp channel in discord. Do something like pings.playEmote1 or pings.setArmorVisibility. +::: ```lua @@ -77,11 +82,11 @@ local action = mainPage:newAction() :title("My Action") :item("minecraft:stick") :hoverColor(1, 0, 1) - -- Pass in the ping function itself into onLeftClick + -- Pass in the ping function itself into onLeftClick :onLeftClick(pings.actionClicked) ``` -And there you have it. An Action that correctly executes it's contents across all clients. +And there you have it, an action that correctly executes its contents across all clients. While this will correctly sync the timing of the execution of the ping function with all clients, it needs a slight modification if you want to send arguments with the ping. @@ -102,18 +107,22 @@ local action = mainPage:newAction() What we are doing is wrapping the call to the ping function inside another function. -The code below is a common mistake beginners can fall into.
-While the code might seem correct to those less code literate, it translates to "call the ping function, then assign the return result to the leftClick field".
-A ping will never have a return value, meaning leftClick is being assigned the value nil, meaning nothing. +:::tip + +The code below is a common mistake beginners can fall into. ```lua mainPage:newAction() :onLeftClick(pings.actionClicked2(math.random())) - -- Do not do use this code. It will not work. + -- This code will not work. ``` -Here is the full copy paste for an example Action Wheel +While the code might look correct at first, what it actually does is immediately invoke `pings.actionClicked2` with a random number as an argument. It then attempts to assign whatever this function returns to the `onLeftClick` event. Since `pings.actionClicked2` is a ping function, which never return a value, `onLeftClick` receives `nil`, effectively assigning nothing. This results in no action being performed when the action is clicked. + +::: + +Here is a complete example of an action wheel. ```lua @@ -133,32 +142,30 @@ local action = mainPage:newAction() ### Further Reading -Go [here](../globals/Action-Wheel/Action.md) for more information on Actions, like making your action [toggleable](../globals/Action-Wheel/Action.md#setOnToggle). +Go [here](../globals/Action-Wheel/Action.md) for more information on actions, like [making your action toggleable](../globals/Action-Wheel/Action.md#setOnToggle). ## Advanced Action Wheel -### Multi Page Setup +### Multi-Page Setup -Creating a network of Pages can be overwhelming. Lets try to rectify that. +Creating a network of pages can be overwhelming. Let's try to rectify that. -This method for creating a Page Network divides the Pages into seperate, isolated files. These files return an Action that can be added to a different page. This Action will set the cuurrent page to the page in the file, but it first stores a reference to the Page it came from. That way when you want to go back to the previous page, its as simple as setting the current page to the stored Page. +This method for creating a page network divides the pages into separate, isolated files. These files return an action that can be added to a different page. This action will set the current page to the page in the file, but it first stores a reference to the page it came from. That way, when you want to go back to the previous page, it's as simple as setting the current page to the stored page. -This allows Pages to be modular and easily reorganized if needed. More importantly, it can help make multiple pages less overwhelming. +This structure allows pages to be modular and easily reorganized if necessary; more importantly, it can help make multiple pages less overwhelming. -```lua ---ActionWheel.lua +```lua title="ActionWheel.lua" -- This file controls the root Page. All Pages are 'children' of this Page. -local mainpage = action_wheel:newPage() --- setAction is used to add an Action that already exists to this Page --- You need to specify the slot the Action wil go into, but -1 can be used to put it in the next available slot. -mainpage:setAction(-1, require("Page1")) -mainpage:setAction(-1, require("Page2")) -action_wheel:setPage(mainpage) +local mainPage = action_wheel:newPage() +-- setAction is used to add an Action that already exists to this Page +-- You need to specify the slot the Action wil go into, but -1 can be used to put it in the next available slot. +mainPage:setAction(-1, require("Page1")) +mainPage:setAction(-1, require("Page2")) +action_wheel:setPage(mainPage) ``` -```lua ---Page1.lua +```lua title="Page1.lua" -- Create the Page local page = action_wheel:newPage() -- Define the Actions within the Page (These are dummy example Actions) @@ -176,9 +183,9 @@ page:newAction() action_wheel:setPage(prevPage) end) --- Page:newAction automatically adds the Action to the Page. --- This is unwanted, so action_wheel:newAction() is used so just make an Action. --- This is the Action that will be returned by require and will be used to navigate to this file's Page +-- Page:newAction automatically adds the Action to the Page. +-- This is unwanted, so action_wheel:newAction() is used so just make an Action. +-- This is the Action that will be returned by require and will be used to navigate to this file's Page return action_wheel:newAction() :title("Page1") :onLeftClick(function() @@ -190,9 +197,8 @@ return action_wheel:newAction() ``` -```lua ---Page2.lua --- Page2 is just to show that the entire process can be repeated verbatum, so long as the variables are local. +```lua title="Page2.lua" +-- Page2 is just to show that the entire process can be repeated verbatim, so long as the variables are local. local page = action_wheel:newPage() page:newAction():title():color():onLeftClick() page:newAction():title():color():onLeftClick() @@ -224,7 +230,7 @@ This example will correctly set the default visibility of a theoretical jetpack ```lua -- This variable's initial value will control the default state of the togglable thing. local jetpackEnabled = true -local jetpackModel = models.model.Body.Jetpack -- reference a ModelPart for convinience +local jetpackModel = models.model.Body.Jetpack -- reference a ModelPart for convenience local function setJetpack(bool) jetpackEnabled = bool -- this will be a ping function, so we still need to set the client's variable for when it is used in the toggle. jetpackModel:setVisible(bool) @@ -242,14 +248,14 @@ function events.tick() end -- Page boilerplate -local mainpage = action_wheel:newAction() -action_wheel:setPage(mainpage) +local mainPage = action_wheel:newAction() +action_wheel:setPage(mainPage) -- calling a ping in the script initialization is a bad idea, hence why the reference to the normal function is needed setJetpack(jetpackEnabled) -mainpage:newAction() +mainPage:newAction() :title("Enable Jetpack") :toggleTitle("Disable Jetpack") :onToggle(pings.setJetpack) -- use the ping for the action toggle, as that is still needs to be pinged - :toggled(jetpackEnabled) -- the toggled function sets the internal state of the Toggle Action. It *does not* call toggle or untoggle. + :toggled(jetpackEnabled) -- the toggled function sets the internal state of the Toggle Action. It *does not* call toggle or untoggle. ``` diff --git a/docs/tutorials/Animations.md b/docs/tutorials/Animations.md index a10ad3a2..d062ed5c 100644 --- a/docs/tutorials/Animations.md +++ b/docs/tutorials/Animations.md @@ -1,16 +1,15 @@ +import Image from '@site/src/components/Image'; +import Emoji from '@site/src/components/Emoji'; + Figura can play animations from Blockbench using the Animation API. ## Playing an Animation -In order to play an animation you need to index the animation through the Blockbench model it is in and the animations global. - -Let's say we have a Blockbench model named example - - +In order to play an animation you need to index the animation through the Blockbench model it is in and the `animations` global. -and an animation named idle +Let's say we have a Blockbench model named `example.bbmodel`, and within it an animation named `idle` - + If we want to play this animation we can use this code: @@ -18,17 +17,17 @@ If we want to play this animation we can use this code: animations.example.idle:play() ``` -animations stores all the animation data for every Blockbench model.
+`animations` stores all the animation data for every Blockbench model. -The next part of the index is always the Blockbench model name that contains the animation you want to play, in our case this is example.bbmodel (if your Blockbench model is in a subfolder, that will need to be included as well, but you can find more information about that in ModelPart Indexing) +The next part of the index is always the Blockbench model name that contains the animation you want to play, in our case this is `example.bbmodel` (if your Blockbench model is in a subfolder, that will need to be included as well, but you can find more information about that in ModelPart Indexing) -And the last is always the animation name, in this case idle. +And the last is always the animation name, in this case `idle`. ## Blockbench is Tricking You If you're looking at your animation in Blockbench and there's two names, the smaller name in gray is the actual animation name. - + **You can't use the method above to play the animation if it looks like this iamge** @@ -37,7 +36,7 @@ You have two options: Rename the animation, or deal with the long animation name ### Option One: Rename the animation - + ### Option Two: @@ -49,7 +48,7 @@ animations.example["animation.model.idle"]:play() ## Alternatives to play() -There is another function that can play animations, setPlaying(bool) +There is another function that can play animations, `setPlaying(bool)` You can put a boolean value inside the parenthesis for the function and it will play the animation if the boolean is true, or stop it if the boolean is false @@ -66,14 +65,15 @@ function events.tick() end ``` -And now our animation idle will play whenever we're crouching! +And now our animation `idle` will play whenever we're crouching! This methodology can be expanded infinitely but it gets more complex the more animations you add. ## Simple Idle-Walk-Sprint-Crouch Setup As an example we'll do code for a set of four animations: idle, walk, sprint, and crouch. Here's our animations in our Blockbench model. - + + ```lua function events.tick() @@ -97,38 +97,39 @@ end ## Common Errors -### Fixing the index error +### Fixing the Index Error -You might run into some script errors while doing this, here's some solutions to attempt to index ? (a nil value) +You might run into some script errors while doing this, here's some solutions to `attempt to index ? (a nil value)` The error will tell you about a key, the key is AFTER the part that's experiencing an incorrect. - + -Like in this example, it says that setPlaying is the key, so we know that the problem is BEFORE it. +Like in this example, it says that `setPlaying` is the key, so we know that the problem is BEFORE it. You'll notice that the animation name is misspelled, once you fix that the error will go away or change. - + -Here it is again, but this time the key is idle, meaning the problem is with the Blockbench model name. +Here it is again, but this time the key is `idle`, meaning the problem is with the Blockbench model name. You'll notice that it's misspelled in this version, fixing it will make the error go away or change. -### Errors inside a keyframe +### Errors Inside a Keyframe Errors inside keyframes are vary vastly, but you can indentify them by the name of the animation in the error. Here's three examples: - + + How you fix this will greatly depend on what the error is. ## Overriding Vanilla Animations -You can override vanilla animations using the override setting in Blockbench, this is set per-animation and it overrides per-part and per-channel (rotation, position, scale). -It only overrides while the animation is playing. - +You can override vanilla animations using the override setting in Blockbench, this is set per-animation and it overrides per-part and per-channel (rotation, position, scale). It only overrides while the animation is playing. + + - + ## Community Resources diff --git a/docs/tutorials/Avatar Metadata.md b/docs/tutorials/Avatar Metadata.md index fd2fb9a5..f08ad848 100644 --- a/docs/tutorials/Avatar Metadata.md +++ b/docs/tutorials/Avatar Metadata.md @@ -2,13 +2,13 @@ import Emoji from '@site/src/components/Emoji'; import FileTreeRoot from '@site/src/components/FileTree/Root'; import FileTreeNode from '@site/src/components/FileTree/Node'; - avatar.json is the file that contains Avatar Metadata. It tells Figura specific information about the avatar. + `avatar.json` is the file that contains Avatar metadata. It tells Figura specific information about the avatar. -## Json Basics +## JSON Basics The format that metadata is stored in is JSON. More specifically, a JSON object. It behaves very similar to a Lua table, it just uses different syntax. However, JSON has a very strict syntax and any errors will cause the avatar to fail to load. -JSON objects operate on key value pairs. Keys are separated from their values using colons (:), and entries are separated with commas (,). Unlike Lua tables, keys must be strings. +JSON objects operate on key value pairs. Keys are separated from their values using colons (`:`), and entries are separated with commas (`,`). Unlike Lua tables, keys must be strings. ```json { @@ -25,10 +25,11 @@ JSON objects operate on key value pairs. Keys are separated from their values us Figura looks for specific keys in this JSON object and does things based on the value. Remember that all of these keys are optional. You only need to define the ones you care about. -### "name" : String +### `name` : String -The value of this key determines the name of the avatar. This name is showed on the avatar information sidebar on the right of the Wardrobe, but also determines the name used to find the avatar on the left of the Wardrobe.
-If this key is not present, the name of the folder containing the avatar.json file is used. +The value of this key determines the name of the avatar. This name is showed on the avatar information sidebar on the right of the Wardrobe, but also determines the name used to find the avatar on the left of the Wardrobe. + +If this key is not present, the name of the folder containing the `avatar.json` file is used. ```json { @@ -36,7 +37,7 @@ If this key is not present, the name of the folder containing the : String +### `description` : String The value of this key will appear below the avatar's name in the wardrobe. @@ -47,7 +48,7 @@ The value of this key will appear below the avatar's name in the wardrobe. } ``` -### "authors" : String[] +### `authors` : String[] The value of this key is an array of strings. An array can contain many different values within itself, and Figura expects these values to be strings. The values are used in the Authors field in the avatar information sidebar. @@ -59,14 +60,13 @@ The value of this key is an array of strings. An array can contain many differen } ``` -### "author" : String +### `author` : String -A place for a single author, should you dislike "authors". Does the exact same thing as "authors" with only 1 element.
-If the "authors" key is present, this key is ignored. +A place for a single author, should you dislike `authors`. Does the exact same thing as `authors` with only 1 element. If the `authors` key is present, this key is ignored. -### "version" : String +### `version` : String -A place to define a [Semantic Versioning](https://semver.org/) version. You can define the lowest possible Figura version that this avatar will run on. If another client uses a Figura version that is less than the version defined here, a warning badge will appear on your nameplate for them. If they hover over it, it will state that their Figura version is lower than what this avatar was designed to run on. If this key does not exist, Figura will use the version that was used to load the avatar.
+A place to define a [Semantic Versioning](https://semver.org/) version. You can define the lowest possible Figura version that this avatar will run on. If another client uses a Figura version that is less than the version defined here, a warning badge will appear on your nameplate for them. If they hover over it, it will state that their Figura version is lower than what this avatar was designed to run on. If this key does not exist, Figura will use the version that was used to load the avatar. ```json { @@ -77,9 +77,9 @@ A place to define a [Semantic Versioning](https://semver.org/) version. You can } ``` -### "color" : String +### `color` : String -This key defines the color of the Figura mark on your nameplate. It must be a string in the format of a 3 character hex code or a 6 character hex code. For example, both "3ab" and "FF00FF" are valid inputs. If this key does not exist, the color "5AAAFF" will be used. +This key defines the color of the Figura mark on your nameplate. It must be a string in the format of a 3 character hex code or a 6 character hex code. For example, both `3ab` and `FF00FF` are valid inputs. If this key does not exist, the color `5AAAFF` will be used. ```json { @@ -91,10 +91,11 @@ This key defines the color of the Figura mark on your } ``` -### "autoScripts" : String[] +### `autoScripts` : String[] + +By default, every single script file in the avatar will execute in an undefined order. The `require` function can be used to control when a script is first executed, but some may prefer to define the script order in the metadata. This key is an array of strings that define which scripts run and in which order. Scripts not defined here will not run by default on avatar init, but can still be ran via `require`. A script is specified via it's file name without the `.lua` extension. If a script is in a subfolder, that folder must also be defined, with the folder separator being a period (`.`). -By default, every single script file in the avatar will execute in an undefined order. The require function can be used to control when a script is first executed, but some may prefer to define the script order in the metadata. This key is an array of strings that define which scripts run and in which order. Scripts not defined here will not run by default on avatar init, but can still be ran via require. A script is specified via it's file name without the .lua extension. If a script is in a subfolder, that folder must also be defined, with the folder separator being a period (.).
-Consider the following avatar:
+Consider the following avatar: @@ -118,13 +119,13 @@ Consider the following avatar:
-To make only RainbowNameplate.lua run on avatar init, the autoScripts would look like
+To make only `RainbowNameplate.lua` run on avatar init, the `autoScripts` would look like ```json "autoScripts":["libs.RainbowNameplate"] ``` -For our example metadata file, we will state that only script.lua will run by default, and the script itself will call require on the library scripts which will "import" them into itself. You may be thinking "whats the point of "autoScripts" if require is objectively better at controlling script load order?", To which my response would be "I don't know". But if you give an empty array, then no script will run which can be useful for debugging. +For our example metadata file, we will state that only `script.lua` will run by default, and the script itself will call `require` on the library scripts which will "import" them into itself. You may be thinking "whats the point of `autoScripts` if `require` is objectively better at controlling script load order?", To which my response would be "I don't know". But if you give an empty array, then no script will run which can be useful for debugging. ```json { @@ -137,10 +138,10 @@ For our example metadata file, we will state that only } ``` -### "autoAnims" : String[] +### `autoAnims` : String[] -This key defines which animations should start playing when the avatar first loads. The string to reference an animation follows the pattern "modelPath.animName". -Consider the following avatar:
+This key defines which animations should start playing when the avatar first loads. The string to reference an animation follows the pattern `modelPath.animName`. +Consider the following avatar: @@ -164,11 +165,13 @@ Consider the following avatar:
-If we want the animation "idle" in the bbmodel player.bbmodel, we would include the string "player.idle" in the "autoAnims" array.
-Folder seperation is done with a period (.) instead of slash (/).
-If we want the animation "spin" in the model halo.bbmodel, we would include the string "accessories.halo.spin" in the "autoAnims" array.
-This is not table indexing like how you would index the `animations` table to get an Animation. It is just string concatenation.
-autoAnims has a very niche use case as 99% of the time you have animations that you only want playing sometimes or want to play on a trigger. The only real use case is for a constantly playing looping animation that you don't want to waste ~8 instructions on play at the beginning of a script, or perhaps you have an avatar that does not have any script files and you want to keep it that way. +Folder separation is done with a period (`.`) instead of slash (`/`). + +If we want the animation `idle` in the bbmodel `player.bbmodel`, we would include the string `player.idle` in the `autoAnims` array If we want the animation `spin` in the model `halo.bbmodel`, we would include the string `accessories.halo.spin` in the `autoAnims` array. + +This is not table indexing like how you would index the `animations` table to get an Animation. It is just string concatenation. + +`autoAnims` has a very niche use case as 99% of the time you have animations that you only want playing sometimes or want to play on a trigger. The only real use case is for a constantly playing looping animation that you don't want to waste ~8 instructions on play at the beginning of a script, or perhaps you have an avatar that does not have any script files and you want to keep it that way. ```json { @@ -182,11 +185,13 @@ This is not table indexing like how you would index the `animations` table to ge } ``` -### "ignoredTextures" : String[] +### `ignoredTextures` : String[] + +This key defines which textures should be ignored when loading the avatar. This is useful for when you have a cube that gets its texture set via code, but since all cubes must have a Blockbench texture for Figura to even load the cube, you will either have to waste space with a dummy texture or use another texture in the model, which probably won't look good on the cube. This key allows you to have that dummy texture in Blockbench without having to waste precious bytes on having that texture loaded with the avatar. -This key defines which textures should be ignored when loading the avatar. This is useful for when you have a cube that gets its texture set via code, but since all cubes must have a blockbench texture for Figura to even load the cube, you will either have to waste space with a dummy texture or use another texture in the model, which probably won't look good on the cube. This key allows you to have that dummy texture in blockbench without having to waste precious bytes on having that texture loaded with the avatar.
-Referencing a texture is exactly the same format as getting a Texture object with the textures global.
-Consider this avatar:
+Referencing a texture is exactly the same format as getting a Texture object with the `textures` global. + +Consider this avatar: @@ -210,7 +215,7 @@ Consider this avatar:
-Hypothetically, the armor of this avatar is being handled by armorAidLib.lua. It changes the texture of cubes to the vanilla armor textures. There is no need to have the diamond_layer_1 and diamond_layer_2 textures in the bbmodel, but setting the cubes to use skin.png will make editing the model a pain. So we remove both unused textures. +Hypothetically, the armor of this avatar is being handled by `armorAidLib.lua`. It changes the texture of cubes to the vanilla armor textures. There is no need to have the `diamond_layer_1` and `diamond_layer_2` textures in the bbmodel, but setting the cubes to use `skin.png` will make editing the model a pain. So we remove both unused textures. ```json { @@ -225,12 +230,15 @@ Hypothetically, the armor of this avatar is being handled by : \{"ModelPart" : \{"Customization" : "String"}} +### `customizations` : \{"ModelPart" : \{"Customization" : "String"}} + +Does that Type identifier make any sense? Not really, but thats what the `customizations` property is. + +`customizations` allows for modifications to ModelParts that cant be done in Blockbench. You can still do this stuff via script, but the intent is for an avatar that does not have a script to still have access to some functionality. -Does that Type identifier make any sense? Not really, but thats what the "customizations" property is.
-"customizations" allows for modifications to ModelParts that cant be done in BlockBench. You can still do this stuff via script, but the intent is for an avatar that does not have a script to still have access to some functionality.
-"customizations" itself is a JSON object. The keys of that object are references to ModelParts, with the values being another JSON object. _That_ object contains key value pairs that operate on the referenced ModelPart.
-Consider the following avatar:
+`customizations` itself is a JSON object. The keys of that object are references to ModelParts, with the values being another JSON object. _That_ object contains key value pairs that operate on the referenced ModelPart. + +Consider the following avatar: @@ -248,8 +256,9 @@ Consider the following avatar:
-To target the Head, the correct key to use would be "player.Head".
-To target the ribbon, the correct key to use would be "accessories.ribbon".
+To target the `Head`, the correct key to use would be `player.Head`. + +To target the `ribbon`, the correct key to use would be `accessories.ribbon`. ```json { @@ -262,9 +271,9 @@ To target the ribbon, the correct key Now for the keys that work inside these sub-objects. -#### "primaryRenderType" : String +#### `primaryRenderType` : String -Sets the RenderType to use for the Primary/Default texture. The default primaryRenderType is "TRANSLUCENT". +Sets the RenderType to use for the Primary/Default texture. The default primaryRenderType is `TRANSLUCENT`. ```json { @@ -277,9 +286,9 @@ Sets the RenderType to use for the Primary/Default texture. The default primaryR } ``` -#### "secondaryRenderType" : String +#### `secondaryRenderType` : String -Sets the RenderType to use for the Secondary/Emissive/\_e texture. The default secondaryRenderType is "EMISSIVE". +Sets the RenderType to use for the Secondary/Emissive/`\_e` texture. The default secondaryRenderType is `EMISSIVE`. ```json { @@ -294,9 +303,9 @@ Sets the RenderType to use for the Secondary/Emissive/\_e texture. } ``` -#### "parentType" : String +#### `parentType` : String -Keywords in BlockBench set the ParentType of the ModelPart. This key overrides that, or sets one if there is no Keyword. The default ParentType is "None" +Keywords in Blockbench set the ParentType of the ModelPart. This key overrides that, or sets one if there is no Keyword. The default ParentType is `None` ```json { @@ -312,7 +321,7 @@ Keywords in BlockBench set the ParentType of the ModelPart. This key overrides t } ``` -#### "moveTo" : String +#### `moveTo` : String Forces the ModelPart reference given to be a child of this ModelPart. This is useful if you like to organize your avatar into separate bbmodels. You can use this to stitch them together. @@ -331,9 +340,9 @@ Forces the ModelPart reference given to be a child of this ModelPart. This is us } ``` -#### "visible" : Boolean +#### `visible` : Boolean -Overrides the visibility defined in BlockBench. Useful to be able to hide ModelParts in BlockBench to edit the model more easily, without it affecting the final result of the Avatar. +Overrides the visibility defined in Blockbench. Useful to be able to hide ModelParts in Blockbench to edit the model more easily, without it affecting the final result of the Avatar. ```json { @@ -351,9 +360,9 @@ Overrides the visibility defined in BlockBench. Useful to be able to hide ModelP } ``` -#### "remove" : Boolean +#### `remove` : Boolean -This customization will prevent the targeted ModelPart from loading at all.
+This customization will prevent the targeted ModelPart from loading at all. ```json { @@ -365,9 +374,10 @@ This customization will prevent the targeted ModelPart from loading at all.
} ``` -#### "smooth" : Boolean +#### `smooth` : Boolean + +This customization must be applied directly to a mesh object. -This customization must be applied directly to a mesh object.
This will calculate the vertex normals so that the mesh appears smooth, reducing the visibility of individual triangles. ```json @@ -380,7 +390,7 @@ This will calculate the vertex normals so that the mesh appears smooth, reducing } ``` -## Final Example avatar.json +## Final Example `avatar.json` ```json { diff --git a/docs/tutorials/Custom-Items.md b/docs/tutorials/Custom-Items.md index e9399114..8b7b5b96 100644 --- a/docs/tutorials/Custom-Items.md +++ b/docs/tutorials/Custom-Items.md @@ -10,13 +10,13 @@ You'll need to use the Item [keyword](../enums/ModelPartParentTypes) and the ite ## Item Keyword -If you give a Blockbench group the Item keyword (by starting the group name with Item) it will be primed and ready to be used as an item. Without the event the Item group will vanish- and so will every item you hold. +If you give a Blockbench group the Item keyword (by starting the group name with `Item`) it will be primed and ready to be used as an item. Without the event the Item group will vanish- and so will every item you hold. ## Item Render Event The item_render event runs once a frame for every item you're holding (so, a max of two) and do their own things in their version of the event. -In order to make the Item show up you must return it in the item_render event. This example assumes the bbmodel is named model and that the keyworded group is named Item. If you wish to test this change model to your bbmodel name and the Item group to your version. +In order to make the Item show up you must return it in the item_render event. This example assumes the bbmodel is named `model` and that the keyworded group is named Item. If you wish to test this change `model` to your bbmodel name and the Item group to your version. ```lua function events.item_render() @@ -35,7 +35,7 @@ function events.item_render(item, mode, pos, rot, scale, left) end ``` -This is storing all the values you can get, but in most cases you only need item and sometimes mode. Let's replace bows, shields, and all swords. These are all for a blockbench model that looks like this: +This is storing all the values you can get, but in most cases you only need item and sometimes mode. Let's replace bows, shields, and all swords. These are all for a Blockbench model that looks like this: @@ -59,7 +59,7 @@ end The find function is searching the id for the word 'sword' so you don't need to type in every single sword id. This also makes it compatible with modded swords. -## Things To Note +## Things to Note 1. Do _not_ put the Item group inside any other group. The Blockbench outliner should look like this: diff --git a/docs/tutorials/Emissive Textures.md b/docs/tutorials/Emissive Textures.md index f4edfa73..a344c262 100644 --- a/docs/tutorials/Emissive Textures.md +++ b/docs/tutorials/Emissive Textures.md @@ -1,29 +1,35 @@ import Emoji from '@site/src/components/Emoji'; +import Image from '@site/src/components/Image'; This page describes everything to know about Emissive Textures. -## Defining a Texture as Emissive +## Defining a Texture As Emissive -Every ModelPart in BlockBench has a reference to a single texture. When Figura loads the avatar, Figura looks for a texture with the same name as the texture used by the ModelPart but with \_e added to the end of it. For example, the emissive texture used by ModelParts that use texture.png will use texture_e.png as their emissive texture.
-\_e is one of the [texture suffixes](../start_here/BlockBench#texture-suffix) that Figura looks for when loading an avatar. +Every ModelPart in Blockbench has a reference to a single texture. When Figura loads the avatar, Figura looks for a texture with the same name as the texture used by the ModelPart but with `\_e` added to the end of it. For example, the emissive texture used by ModelParts that use `texture.png` will use `texture_e.png` as their emissive texture. + +`\_e` is one of the [texture suffixes](../start_here/Blockbench#texture-suffix) that Figura looks for when loading an avatar. ## Emissive Texture Behavior - + + +The pixels on a Texture using the `EMISSIVE` [RenderType](../enums/RenderTypes) are not interpreted the same was as a regular texture. + +First of all, the alpha values of pixels are ignored. This means that the emissive texture itself cannot be halfway visible. Its either the pixel is completely opaque, or completely gone. No in between. + +On the texture below, both pixels will render the exact same. Even though they appear to be 2 distinct colors, the right color has an alpha value of `139` and is blending with the gray GitHub background. They have the exact same RGB values and will be rendered exactly the same under the `EMISSIVE` RenderType. -The pixels on a Texture using the "EMISSIVE" [RenderType](../enums/RenderTypes) are not interpreted the same was as a regular texture.
+ -First of all, the alpha values of pixels are ignored. This means that the emissive texture itself cannot be halfway visible. Its either the pixel is completely opaque, or completely gone. No in between.
-On the texture below, both pixels will render the exact same. Even though they appear to be 2 distinct colors, the right color has an alpha value of 139 and is blending with the gray GitHub background. They have the exact same RGB values and will be rendered exactly the same under the "EMISSIVE" RenderType.
- +Second, the "brightness" of a pixel is what determines the intensity of the emissive glow. If you know HSV, its the Value that controls this property. Emissive Intensity controls how bright the pixel will render, but also how much of the pixel behind it will show through. -Second, the "brightness" of a pixel is what determines the intensity of the emissive glow. If you know HSV, its the Value that controls this property. Emissive Intensity controls how bright the pixel will render, but also how much of the pixel behind it will show through.
-On the texture below, both pixels will render with the same color. The pixel on the left will render with max brightness, not allowing the pixels on the base texture to blend through. The pixel on the right won't glow as much, but allows the pixels on the base texture to blend through.
- +On the texture below, both pixels will render with the same color. The pixel on the left will render with max brightness, not allowing the pixels on the base texture to blend through. The pixel on the right won't glow as much, but allows the pixels on the base texture to blend through. + + ## Iris Emissives -If you use Iris, regardless of the fact of if you are currently using custom shaders, the "EMISSIVE" RenderType is modified to use the alpha value when rendering the emissive texture. How exactly is not known. Experimentation is required. +If you use Iris, regardless of the fact of if you are currently using custom shaders, the `EMISSIVE` RenderType is modified to use the alpha value when rendering the emissive texture. How exactly is not known. Experimentation is required. ## Emissive Render Types @@ -51,4 +57,8 @@ You can set the render type to "Eyes" like this models:setSecondaryRenderType("Eyes") ``` -Note: The glow on the paperdoll and the skull may look slightly different. +:::note + +The glow on the paperdoll and the skull may look slightly different. + +::: diff --git a/docs/tutorials/How-To-Read-Documentation.md b/docs/tutorials/How-To-Read-Documentation.md index d52f6574..d6acd41a 100644 --- a/docs/tutorials/How-To-Read-Documentation.md +++ b/docs/tutorials/How-To-Read-Documentation.md @@ -1,22 +1,22 @@ -# How To Read Documentation +# How to Read Documentation **This article is a WIP.** As of writing this article, the GitHub wiki is not complete, but there are other sources of documentation for Figura out there. The most updated one is called Figs and it's made and managed by GitHub user applejuiceyy. [Here's a link](https://applejuiceyy.github.io/figs/). -User GrandpaScout has their [VSDocs](https://github.com/GrandpaScout/FiguraRewriteVSDocs) which are used in conjunction with the text/code editor Visual Studio Code. These docs will help autofill function names and blockbench model paths for you. +User GrandpaScout has their [VSDocs](https://github.com/GrandpaScout/FiguraRewriteVSDocs) which are used in conjunction with the text/code editor Visual Studio Code. These docs will help autofill function names and Blockbench model paths for you. -In-game, Figura has a custom command to find documentation. /figura docs +In-game, Figura has a custom command to find documentation. `/figura docs` ## The Basics ### Globals -Globals are where functions that allow you to access various information are stored. For instance, functions relating to player data are stored in the global player, and functions relating to the avatar's models are stored in the global models. +Globals are where functions that allow you to access various information are stored. For instance, functions relating to player data are stored in the global `player`, and functions relating to the avatar's models are stored in the global `models`. ### Enums -Enums are not functions, but rather lists of key words a function may return or take as an argument. For example, the ParentTypes enums contains all the parent types you could set a modelPart to (which are equivalent to the Blockbench keywords). On the other hand, the EntityPoses enums contains all the entity poses (including non-player poses) that an entity can achieve, as returned by getPose() +Enums are not functions, but rather lists of key words a function may return or take as an argument. For example, the `ParentTypes` enums contains all the parent types you could set a modelPart to (which are equivalent to the Blockbench keywords). On the other hand, the `EntityPoses` enums contains all the entity poses (including non-player poses) that an entity can achieve, as returned by `getPose()` ## Reading Figs @@ -30,23 +30,23 @@ Regardless of if you select a version or not you will see a list of words on the Figs has a search function which will find any word in the name or description of a function, so if you don't know what global a function is in, you can use the search function to keyword search for it. (For example, if you want to change the camera, search for camera and scroll) -Let's say we want to make a custom elytra that turns off/on depending on if we're wearing an elytra. We're a player, so all of our information is going to be in the player API. On the left sidebar scroll down until you find player underneath the globals section. Aside from scrolling through the entire player API list you could search for the word 'item' (as we are looking for item information) until you find getItem() +Let's say we want to make a custom elytra that turns off/on depending on if we're wearing an elytra. We're a player, so all of our information is going to be in the player API. On the left sidebar scroll down until you find `player` underneath the globals section. Aside from scrolling through the entire player API list you could search for the word 'item' (as we are looking for item information) until you find `getItem()` ### How To Read What's Being Given -There's going to be some information there, and all of it is necessary. You can click on PlayerAPI.getItem to open the full page for the function (though this doesn't provide more information) +There's going to be some information there, and all of it is necessary. You can click on `PlayerAPI.getItem` to open the full page for the function (though this doesn't provide more information) -PlayerAPI.getItem tells us that the function getItem is in the PlayerAPI. Functions in the player API are accessed via the player global so the function can be accessed by writing player:getItem(). But it doesn't tell us how to get all the information we want out of it yet. +`PlayerAPI.getItem` tells us that the function `getItem` is in the PlayerAPI. Functions in the player API are accessed via the `player` global so the function can be accessed by writing `player:getItem()`. But it doesn't tell us how to get all the information we want out of it yet. -Look down until you see overload 1: this next bit of information is the second piece of the puzzle +Look down until you see `overload 1:` this next bit of information is the second piece of the puzzle -PlayerAPI:getItem(index: Integer): ItemStack is giving us **four** very important pieces of information, the first two we've already gone over. +`PlayerAPI:getItem(index: Integer): ItemStack` is giving us **four** very important pieces of information, the first two we've already gone over. -The third piece of information is what's inside the brackets (). In this case it's index: Integer. In this context, "index" refers to the item slot being checked. An integer is a whole number, so this tells us that the slot to check is determined by putting a whole number in the brackets. +The third piece of information is what's inside the brackets `()`. In this case it's `index: Integer`. In this context, "index" refers to the item slot being checked. An integer is a whole number, so this tells us that the slot to check is determined by putting a whole number in the brackets. -Looking back up at the description of the item, Figs tells us slots are indexed with 1 as the main hand, 2 as the off hand, and 3,4,5,6 as the 4 armor slots from the boots to the helmet. In short, the integer we enter as an argument will dictate what slot it will search. Figs says 6 is the helmet and it goes down to the boots, and we want the chestplate slot so 5 is the integer we must give it. +Looking back up at the description of the item, Figs tells us `slots are indexed with 1 as the main hand, 2 as the off hand, and 3,4,5,6 as the 4 armor slots from the boots to the helmet`. In short, the integer we enter as an argument will dictate what slot it will search. Figs says 6 is the helmet and it goes down to the boots, and we want the chestplate slot so 5 is the integer we must give it. -At this point we have this: player:getItem(5) and we're going to test that it's working with a bit of code +At this point we have this: `player:getItem(5)` and we're going to test that it's working with a bit of code ```lua function events.tick() @@ -56,19 +56,19 @@ end And... huzzah! Our game chat is being spammed by the log, and that log is telling us what's in our chestplate slot. -The game is telling us, at the end of the message, that this is an ItemStack. If you look back at figs' overload: PlayerAPI:getItem(index: Integer): ItemStack you'll notice that 'ItemStack' is after the parenthesis. That's because the information after the colon : is what the function is going to return. Essentially, what it's going to give back to us after it's done. +The game is telling us, at the end of the message, that this is an ItemStack. If you look back at figs' overload: `PlayerAPI:getItem(index: Integer): ItemStack` you'll notice that 'ItemStack' is after the parenthesis. That's because the information after the colon `:` is what the function is going to return. Essentially, what it's going to give back to us after it's done. So now we can get information from the chesplate slot, but we're not doing anything with that information yet, we must dive into information given to us via the ItemStack. -In Figs, click on ItemStack and it will bring you to another page that has even more functions on it. +In Figs, click on `ItemStack` and it will bring you to another page that has even more functions on it. -We want to know if this ItemStack is from an elytra. The best way to do this is via the item's id. If you've ever used the /give command, you give yourself an item via the item ID, and it looks like minecraft:stick or something similar. An item's id can also be viewed by turning advanced tooltips on using F3+H. +We want to know if this ItemStack is from an elytra. The best way to do this is via the item's id. If you've ever used the /give command, you give yourself an item via the item ID, and it looks like `minecraft:stick` or something similar. An item's id can also be viewed by turning advanced tooltips on using F3+H. -If you've searched the ItemStack page for id you will easily find the getID() function. +If you've searched the ItemStack page for id you will easily find the `getID()` function. -Its overload looks like this: ItemStack:getID(): String +Its overload looks like this: `ItemStack:getID(): String` -Like before, getID() is in ItemStack, meaning it wants an ItemStack, but we don't have an ItemStack API like the player API, we can't do ItemStack:getID() because ItemStack is meaningless (it's not in the list of globals). However, player:getItem(5) returns an ItemStack which the getID() function can be used on directly. As such, we can use player:getItem(5):getID() which in our testing log looks like this: +Like before, getID() is in ItemStack, meaning it wants an ItemStack, but we don't have an ItemStack API like the player API, we can't do ItemStack:getID() because ItemStack is meaningless (it's not in the list of globals). However, `player:getItem(5)` returns an ItemStack which the `getID()` function can be used on directly. As such, we can use `player:getItem(5):getID()` which in our testing log looks like this: ```lua function events.tick() @@ -76,9 +76,9 @@ function events.tick() end ``` -You might be wondering about putting something in getID's parentehsis, so let's turn our attention back to the overload figs gives us. In ItemStack:getID(): String the parenthesis are empty here. That means no arguments are necessary and nothing should be put in the brackets. Anything given will be ignored. +You might be wondering about putting something in getID's parentehsis, so let's turn our attention back to the overload figs gives us. In `ItemStack:getID(): String` the parenthesis are empty here. That means no arguments are necessary and nothing should be put in the brackets. Anything given will be ignored. -Notably, it's returning a String which is quite literally a string of characters. Putting something in quotes makes it a string. So true is a boolean, but "true" is a string. In our case this string of characters is the id of the item in our chestplate slot. At this point we can compare the string of our item with the string of the elytra id. +Notably, it's returning a String which is quite literally a string of characters. Putting something in quotes makes it a string. So `true` is a boolean, but `"true"` is a string. In our case this string of characters is the id of the item in our chestplate slot. At this point we can compare the string of our item with the string of the elytra id. ```lua function events.tick() @@ -86,9 +86,9 @@ function events.tick() end ``` -This statement is known as an evaluation. The doubled equals sign == tells the game to compare the two values on either side of it. In the case of functions, it will compare the value the function returns. If an elytra is worn then player:getItem(5):getID() will return "minecraft:elytra, which is equal to what we're checking for and as such the game will show true. The evaluation can be combined with other code to do more with it, such as store its value in a variable or put it in an if statement. +This statement is known as an evaluation. The doubled equals sign `==` tells the game to compare the two values on either side of it. In the case of functions, it will compare the value the function returns. If an elytra is worn then `player:getItem(5):getID()` will return `"minecraft:elytra`, which is equal to what we're checking for and as such the game will show `true`. The evaluation can be combined with other code to do more with it, such as store its value in a variable or put it in an if statement. -So, after all this, our elytra detection is player:getItem(5):getID() == "minecraft:elytra". It's using the player API to run getItem() on the player, and then use getID() on the player's item, and then compare it's ID to that of the elytra to find out if we're wearing an elytra or not. +So, after all this, our elytra detection is `player:getItem(5):getID() == "minecraft:elytra"`. It's using the player API to run `getItem()` on the player, and then use `getID()` on the player's item, and then compare it's ID to that of the elytra to find out if we're wearing an elytra or not. For clarification: The log is another function that we put the final result into. It serves to make the information we put in it as an argument to the chat. If you copied the log that will break things diff --git a/docs/tutorials/Keybinds.md b/docs/tutorials/Keybinds.md index 9bc7c1ce..88e40cd7 100644 --- a/docs/tutorials/Keybinds.md +++ b/docs/tutorials/Keybinds.md @@ -2,7 +2,21 @@ Through Figura's keybind API you can have the script listen for key presses to m Keybinds are unsynced information, meaning that without a ping other players cannot know that you pressed a key at all. This guide will be using pings with all the example keybinds. -**Note: Keybinds can be used while the player is unloaded (aka you are out of render distance), if the player API is called during this time your script will error.** You can protect yourself from these errors by adding this check: if not player:isLoaded() then return end as the first line of code run **_inside the ping._** +:::warning + +Keybinds can be used while the player is unloaded, such as when you are out of render distance. +If the player API is called during this time your script will error. + +You can protect yourself from these errors by adding a check at the top of your ping function. For example: + +```lua +function pings.examplePing() + if not player:isLoaded() then return end + -- ...rest of your code +end +``` + +::: ## Example Keybind @@ -12,11 +26,11 @@ First things first, you need to initialize the keybind local exampleKey = keybinds:newKeybind("Keybind Name", "key.keyboard.h") ``` -At this point, the keybind will show up in the avatar's keybind list- accessible via the Figura menu- with the name Keybind Name and assigned to the letter H. But pressing H won't do anything yet. +At this point, the keybind will show up in the avatar's keybind list (accessible via the Figura menu) with the name Keybind Name and assigned to the letter H. But pressing H won't do anything yet. More keybinds ids can be found in the Keybinds: Enums page -There are multiple ways to detect keybinds, but the most common is through press and release as they are easiest to ping. If you're not familiar with pings see [Pings](./Pings). +There are multiple ways to detect keybinds, but the most common is through `press` and `release` as they are easiest to ping. If you're not familiar with pings see [Pings](./Pings). Underneath creating the key we will be tying the press of the key to a ping function. It's done underneath as the code is read top-down and the key must exist first. @@ -27,7 +41,7 @@ exampleKey.press = pings.examplePing This itself won't do anything until we create the function pings.examplePing, this must be done above where press is assigned to the ping function, because the ping function will need to exist before it can be assigned. If it's done beneath nothing will happen. -The false at the end decides whether or not the keybind will function while a gui like the inventory is opening. It can be skipped and the value will be considered false. If it's set to true then this keybind will run even while any gui is open or closed. +The false at the end decides whether or not the keybind will function while a GUI like the inventory is opening. It can be skipped and the value will be considered false. If it's set to true then this keybind will run even while any GUI is open or closed. ```lua function pings.examplePing() @@ -39,7 +53,7 @@ exampleKey.press = pings.examplePing And there we have it! Now this keybind will send Pressed! in chat every time H is pressed. At this point you could put whatever lines of code you wish into the ping function and it will be synced. -Alternatively, release will run the keybind when the key is released rather than when it is first pressed. +Alternatively, `release` will run the keybind when the key is released rather than when it is first pressed. ## Toggling With A Keybind @@ -65,9 +79,9 @@ end -- This time .press is being tied to a function that is then calling the ping, instead of being 'attached' to it directly. ``` -## Detecting When A Key Is Held Down +## Detecting When a Key Is Held Down -If you have the know-how it is possible to use the isPressed() function to detect when a key is being held down, but it's not recommended, as using press and release in conjunction is far more effective. +If you have the know-how it is possible to use the `isPressed()` function to detect when a key is being held down, but it's not recommended, as using press and release in conjunction is far more effective. ```lua local keybindState = false @@ -92,7 +106,7 @@ function events.tick() end ``` -## Using A Vanilla Keybind +## Using a Vanilla Keybind If you want to detect a vanilla action like attacking or walking forwards but want it to be compatible in the case that someone bound forward to an arrow key you can directly get the vanilla keybind and use it. There's multiple ways to accomplish this but we'll use the same method as previous examples. @@ -100,4 +114,4 @@ If you want to detect a vanilla action like attacking or walking forwards but wa local exampleKey = keybinds:newKeybind("Keybind Name", keybinds:getVanillaKey("key.forward")) ``` -This will now detect the forward key regardless of what it's bound to. getVanillaKey() is going to need a key id from a specific list of ids that all correspond to a vanilla keybind. They can be found in the keyIDs enum. +This will now detect the forward key regardless of what it's bound to. `getVanillaKey()` is going to need a key id from a specific list of ids that all correspond to a vanilla keybind. They can be found in the keyIDs enum. diff --git a/docs/tutorials/ModelPart Indexing.md b/docs/tutorials/ModelPart Indexing.md index ef9842ed..4f788807 100644 --- a/docs/tutorials/ModelPart Indexing.md +++ b/docs/tutorials/ModelPart Indexing.md @@ -2,15 +2,15 @@ import Emoji from '@site/src/components/Emoji'; import FileTreeRoot from '@site/src/components/FileTree/Root'; import FileTreeNode from '@site/src/components/FileTree/Node'; -This page describes the process to access any ModelPart from the global ModelPart models +This page describes the process to access any ModelPart from the global ModelPart `models` # Getting a ModelPart -A property of all ModelParts is that you can get a child ModelPart of a parent ModelPart by [indexing](../tutorials/Tables#generic-indexing) the parent with the child's name.
-models itself is a ModelPart. All bbmodel files in the avatar act as child ModelParts to models.
-Everything in the root of a Blockbench project is a child of the bbmodel ModelPart.
-After that, parenting follows the parent structure as defined in the Blockbench OUTLINER.
-For example the cube RightArm,
+A property of all ModelParts is that you can get a child ModelPart of a parent ModelPart by [indexing](../tutorials/Tables#generic-indexing) the parent with the child's name. + +`models` itself is a ModelPart. All bbmodel files in the avatar act as child ModelParts to `models`. Everything in the root of a Blockbench project is a child of the bbmodel ModelPart. After that, parenting follows the parent structure as defined in the Blockbench OUTLINER. + +For example, the cube `RightArm`, @@ -25,14 +25,14 @@ For example the cube RightArm,
-Would be accessed via models.model.RightArm.RightArm +Would be accessed via `models.model.RightArm.RightArm` # Storing a ModelPart -As there is nothing special about indexing straight from models all the time (its just another ModelPart), if a specific ModelPart is used multiple times in a script we can store it in a variable for ease of access. +As there is nothing special about indexing straight from `models` all the time (its just another ModelPart), if a specific ModelPart is used multiple times in a script we can store it in a variable for ease of access. ```lua ---sets a World parented part to match the player's position and body rotation +-- sets a World parented part to match the player's position and body rotation local worldPart = models.model.World function events.RENDER(delta, context) worldPart:setPos(player:getPos(delta) * 16) @@ -40,9 +40,9 @@ function events.RENDER(delta, context) end ``` -# BBmodels in subfolders +# BBmodels in Subfolders -bbmodel files in subfolders are a special case. For them, the folder itself acts as another ModelPart.
+bbmodel files in subfolders are a special case. For them, the folder itself acts as another ModelPart. @@ -55,4 +55,4 @@ bbmodel files in subfolders are a special case. For them, the folder itself acts -The bbmodel Pet.bbmodel would be accessed by models.subfolderA.Pet.
+The bbmodel `Pet.bbmodel` would be accessed by `models.subfolderA.Pet`. diff --git a/docs/tutorials/Particles.md b/docs/tutorials/Particles.md index ea70451a..3989639a 100644 --- a/docs/tutorials/Particles.md +++ b/docs/tutorials/Particles.md @@ -1,4 +1,4 @@ -Using the particle API you can spawn particles from Minecraft. These work similarly to the /particle command in-game. For particles with special properties like dust, they are placed in the name. +Using the particle API you can spawn particles from Minecraft. These work similarly to the `/particle` command in-game. For particles with special properties like dust, they are placed in the name. Most of the article assumes you know to avoid calling the player in init. @@ -24,7 +24,7 @@ particles:newParticle("dust 0 1 1 1", player:getPos()) This will spawn an aqua dust particle as the color values need a number between 0 and 1, the fourth number is the alpha. I excluded the 'minecraft:' mod name to demonstrate that it's unnecessary. -## Spawning At A Part Location +## Spawning at a Part Location To spawn a particle at a modelPart's position you'll need to get the position matrix of that part, and insert it into the position like normal. @@ -32,7 +32,7 @@ To spawn a particle at a modelPart's position you'll need to get the position ma particles:newParticle("explosion", modelPart:partToWorldMatrix():apply()) ``` -Where modelPart is a reference to a real modelPart in your avatar. +Where `modelPart` is a reference to a real modelPart in your avatar. ## An Alternative Method diff --git a/docs/tutorials/Pings.md b/docs/tutorials/Pings.md index f547e619..fccc8631 100644 --- a/docs/tutorials/Pings.md +++ b/docs/tutorials/Pings.md @@ -1,26 +1,26 @@ -With normal mods, there is comunication between the Minecraft Server and it's clients which allows everything to stay in sync.
-Figura is completely client-side. It will never comunicate with the Minecraft Server you are connected to. Figura does not have a server-side component, meaning nothing will happen if you put the mod on a server.
+With normal mods, there is comunication between the Minecraft Server and it's clients which allows everything to stay in sync. Figura, however, is completely client-side. It will never comunicate with the Minecraft server you are connected to. Figura does not have a server-side component, meaning nothing will happen if you put the mod on a server. + +What does this mean for you, the user? It means that certain functionality that only your client has access to will not be synced with other players. -What does this mean for you, the user? It means that certain functionality that only your client has access to will not be synced with other players.
Some examples: -- Keybinds
+- Keybinds - If the Minecraft Server tracked every single keystroke, it would be a major security issue. The exact keystrokes are never sent, only the result of those keystrokes. -- Action Wheel
+- Action Wheel - The Action Wheel is a feature added by Figura. Remember how I said that Figura never comunicates with the Minecraft Server? It should be obvious why the Action Wheel isnt synced. -- HostAPI
- - The HostAPI exclusivly contains variables that only you, the owner of the avatar and the owner of the machine running Minecraft, has access to. All functions contained within are vanilla variables that are not synced with the Minecraft Server. They are wrapped in a nice, explicit package stating that they are never synced. This is unlike the PlayerAPI, which you can assume is always synced (to some extent (I'm looking at you isGrounded)) +- HostAPI + - The HostAPI exclusivly contains variables that only you, the owner of the avatar and the owner of the machine running Minecraft, has access to. All functions contained within are vanilla variables that are not synced with the Minecraft Server. They are wrapped in a nice, explicit package stating that they are never synced. This is unlike the PlayerAPI, which you can assume is always synced (to some extent (I'm looking at you `isGrounded`)) -So how can we sync information with other players if we cannot do it through the Minecraft Server? The answer is Pings.
+So how can we sync information with other players if we cannot do it through the Minecraft Server? The answer is Pings. ## General Pings -Pings utilize Figura's Backend to sync information with other clients.
-Pings are functions that when called, triggers all other clients to call the same function for their instance of your avatar. +Pings are special functions that when called, communicate with Figura's backend to trigger the same function on all other clients. This allows you to sync information with other players. ### Ping Rate Limiting -The backend restricts you on how much data you can send over a period of time.
+The backend restricts you on how much data you can send over a period of time. + The developer given limits are: - 1024 bytes per second @@ -30,30 +30,31 @@ If either of these are reached, the backend will ignore any comunication from yo ### Pingable Values -Pings can send most primitive types and some userdata types.
+Pings can send most primitive types and some userdata types. + All pingable types use a single byte to represent the type of data that is being sent. This byte is not included in the listed byte totals. -- nil - 0 Bytes - - if a type that is not supported is used as a parameter, it will be replaced with nil. -- boolean - 0 Bytes -- integear - 1-4 Bytes - - integears only take up as many bytes as it needs. - - integears are signed. For example, to only use a single byte the value must be between -128 and 127. -- double - 8 Bytes - - If the number has a decimal at all, or is outside the range of a 4 byte integear, it will be sent as a double. -- string - 2+n Bytes - - strings will always use 2 bytes to store the length. +- `nil` - 0 Bytes + - if a type that is not supported is used as a parameter, it will be replaced with `nil`. +- `boolean` - 0 Bytes +- `integear` - 1-4 Bytes + - `integears` only take up as many bytes as it needs. + - `integears` are signed. For example, to only use a single byte the value must be between -128 and 127. +- `double` - 8 Bytes + - If the number has a decimal at all, or is outside the range of a 4 byte `integear`, it will be sent as a `double`. +- `string` - 2+n Bytes + - `strings` will always use 2 bytes to store the length. - Ascii characters will be a single byte each. - UTF-8 characters will be multiple bytes per character. - - The absolute maximum size of string you can send is 65535 characters. If a larger string is sent, it will be truncated. -- table - Too Many Bytes + - The absolute maximum size of string you can send is `65535` characters. If a larger string is sent, it will be truncated. +- `table` - Too Many Bytes - Every key and value is send as data, resulting in high byte costs. - It is recommended to never send a table over pings. -- VectorN - 1+8\*N Bytes +- `VectorN` - 1+8\*N Bytes - Vectors have a single byte that stores the size of the Vector. - - Vectors are always assumed to store doubles. If you have a Vector of integears, I recommend sending them as 3 seperate arguments instead. -- MatrixN - 2+8\*W\*H Bytes - - Matrices store both the width and height of the matrix, then every value as a double. + - Vectors are always assumed to store `doubles`. If you have a Vector of integears, I recommend sending them as 3 seperate arguments instead. +- `MatrixN` - 2+8\*W\*H Bytes + - Matrices store both the width and height of the matrix, then every value as a `double`. ### Ping @@ -81,13 +82,13 @@ When you as the host call the ping, the function will execute for all other clie Do note that if a non-host client reaches a line where a ping gets called, it is completely ignored. No data is sent to the backend, and the contents of the ping will not be executed. -Ping functions can be passed into functions that expect a function as a parameter, such as Action onToggle. +Ping functions can be passed into functions that expect a function as a parameter, such as Action `onToggle`. ```lua actionVariable:onToggle(pings.pingName) ``` -Remember that we are passing the function itself as a variable. The below would be passing the _return result_ of the ping function, which is nigh guarenteed to be nil as Pings _should never_ return a value. +Remember that we are passing the function itself as a variable. The below would be passing the _return result_ of the ping function, which is nigh guarenteed to be `nil` as Pings _should never_ return a value. ```lua --do not do @@ -102,7 +103,7 @@ Situational techniques that may be handy, depending on the use case. Calling a ping function when the script is first loaded is a horrible idea. The ping will only ever execute for other clients when you, the host, load the avatar. Not only that, it may never be executed on other clients, as they might not have your avatar loaded by the time you broadcast the ping. -How do we get around this? Well, when you assign a function to an index in the pings table, the Lua Function gets replaced with a Java Function. This happens because of metatables, specifically the \_\_newindex metamethod. Functions cannot be modified, so if we store the function before assing it to the pings table, we can use it like a regular function, and use the same code as a ping function. +How do we get around this? Well, when you assign a function to an index in the `pings` table, the Lua Function gets replaced with a Java Function. This happens because of metatables, specifically the `\_\_newindex` metamethod. Functions cannot be modified, so if we store the function before assing it to the `pings` table, we can use it like a regular function, and use the same code as a ping function. ```lua local function doThing(state) @@ -111,7 +112,7 @@ local function doThing(state) end pings.doThing = doThing -- doThing and pings.doThing are 2 completely seperate values at this point, as the pings table has replaced the index at pings.doThing with a Java Function that wraps the doThing Lua Function. --- doThing==pings.doThing will return false +-- `doThing==pings.doThing` will return `false` print(doThing, pings.doThing, doThing == pings.doThing) local keybindState = false @@ -126,8 +127,7 @@ function keyA.press() end ``` -The alternative is to reiterate the models.modelA:setVisible(state) models.modelB:setVisible(not state) part of the ping.
-For larger pings it will be combersome to rewrite code that is already defined, which is why this technique is useful. +The alternative is to reiterate the `models.modelA:setVisible(state) models.modelB:setVisible(not state)` part of the ping. For larger pings, it will be cumbersome to rewrite code that is already defined, which is why this technique is useful. ### Byte Array diff --git a/docs/tutorials/Sounds.md b/docs/tutorials/Sounds.md index b36903a4..85215ebe 100644 --- a/docs/tutorials/Sounds.md +++ b/docs/tutorials/Sounds.md @@ -2,9 +2,9 @@ Using Figura you can play custom sounds and sounds from Minecraft itself. This article assumes you know to avoid calling the player in init. -## Playing A Sound +## Playing a Sound -The most common way to play a sound is through the playSound function in the sound API. +The most common way to play a sound is through the `playSound` function in the sound API. ```lua sounds:playSound(soundID, position, volume, pitch, loop) @@ -32,13 +32,13 @@ sounds:playSound("entity.bat.ambient", player:getPos(), 1, 1, false) Playing a custom sound is exactly the same as playing a Minecraft sound, except the sound ID is now the name of the sound file. -Ex: If your file is horn.ogg then your playSound line would look like this: +Ex: If your file is `horn.ogg` then your playSound line would look like this: ```lua sounds:playSound("horn", player:getPos()) ``` -Minecraft will only play specific sound files, namely sounds that are .ogg files. Here's an [online OGG converter](https://audio.online-convert.com/convert-to-ogg). You will want to change the audio channels setting to mono and the audio codec to Vorbis because Minecraft likes the Vorbic codec. +Minecraft will only play specific sound files, namely sounds that are .ogg files. Here's an [online OGG converter](https://audio.online-convert.com/convert-to-ogg). You will want to change the audio channels setting to `mono` and the audio codec to `Vorbis` because Minecraft likes the Vorbic codec. If your custom sound is stored in a subfolder in the avatar, the subfolder name gets added onto the sound name like this: @@ -54,7 +54,7 @@ Mono sounds are half the size of stereo when it comes to file size. Mono also ac Stereo sounds are much bigger (and sounds are already quite big when it comes to file size) and will play for _everyone in the server_ similarly to activating an end portal. There's no way to get around that other than to swap the audio channels to mono. -## Alternative Ways To Play Sounds +## Alternative Ways to Play Sounds If you want to make a long or looping sound follow your movement you're going to need to use a different method for playing sounds. diff --git a/docs/tutorials/Tables.md b/docs/tutorials/Tables.md index 222ba0f3..c25d8e75 100644 --- a/docs/tutorials/Tables.md +++ b/docs/tutorials/Tables.md @@ -10,7 +10,7 @@ local t = {} ## Generic Indexing -table[key] is the way to index a table. You can either get what is currently at that key, or assign a value to that key. There is no limitation to what can be used as keys or values in a table. If you index a table with an unknown key, it will return nil. You can also use variables as a key to index a table using this method. +`table[key]` is the way to index a table. You can either get what is currently at that key, or assign a value to that key. There is no limitation to what can be used as keys or values in a table. If you index a table with an unknown key, it will return `nil`. You can also use variables as a key to index a table using this method. ```lua local v = 6 @@ -26,10 +26,11 @@ print(t["string key, table value"]) --> table 3be7a8 ## String Indexing Shorthand -If that seems like a lot of work to index by a string, yes it is.
-table.key is the shorthand for indexing a table with a string. This has very specific restrictions for what the string can contain. +If that seems like a lot of work to index by a string, yes it is. -- Cannot start with a number (t.2fort will not work. Use [] indexing, or use a different string) +`table.key` is the shorthand for indexing a table with a string. This has very specific restrictions for what the string can contain. + +- Cannot start with a number (`t.2fort` will not work. Use `[]` indexing, or use a different string) - Cannot contain spaces, periods, or other special characters - Cannot be Lua Keywords (true, false, local, function) @@ -42,7 +43,7 @@ t.underscores_are_allowed = true ## Object Oriented Method Indexing -There is one more way to index a table. Many of the functions in Figura take in the object that called said function as the first parameter. This is because every object of the same type has the exact same functions. This is done via table:key().
+There is one more way to index a table. Many of the functions in Figura take in the object that called said function as the first parameter. This is because every object of the same type has the exact same functions. This is done via `table:key()`. ```lua local posA = player:getPos() @@ -52,7 +53,7 @@ local posB = player.getPos(player) ## Initialize Table with Values -You can assign values to keys when the table is initialized. Each key-value pair must be separated by a comma (,)
+You can assign values to keys when the table is initialized. Each key-value pair must be separated by a comma (`,`) ```lua @@ -63,12 +64,12 @@ local a = { ["a"] = 1, ["b"] = 2, }, - -- string shorthand rules still apply. This is equivalent to ["life"] = 42 + -- string shorthand rules still apply. This is equivalent to `["life"] = 42` life = 42, } ``` -If you do not specify an index, the provided values will automatically be assigned a numeric index, starting at 1. This is how arrays are handled in lua, just a table that acts as an array. A table array if you will. Unlike other languages, Lua arrays begin indexing at 1 and functions that take in an array expect the first element at 1. +If you do not specify an index, the provided values will automatically be assigned a numeric index, starting at `1`. This is how arrays are handled in lua, just a table that acts as an array. A table array if you will. Unlike other languages, Lua arrays begin indexing at `1` and functions that take in an array expect the first element at `1`. ```lua @@ -85,10 +86,9 @@ local array = { local array2 = { 42, 36, 1024, 1, "string", v, t } ``` -## Iterating Over a Table +## Iterating over a Table -Iterating over a table is simple.
-You can iterate over every single index using pairs. This will go through every index, but it will be in an undefined order. pairs has 2 values it returns when used in a for loop: the current key, and the current value at that key.
+Iterating over a table is simple. You can iterate over every single index using `pairs`. This will go through every index, but it will be in an undefined order. `pairs` has 2 values it returns when used in a for loop: the current `key`, and the current `value` at that `key`. ```lua for key, value in pairs(t) do @@ -96,7 +96,7 @@ for key, value in pairs(t) do end ``` -If the order of the iteration is important, you can use ipairs, but it only goes over numerical indices. This is what you want to use for table arrays. It starts at index 1, and increments by 1 until the table returns nil. When used in a for loop, ipairs returns the current index and the value at that index.
+If the order of the iteration is important, you can use `ipairs`, but it only goes over numerical indices. This is what you want to use for table arrays. It starts at index `1`, and increments by `1` until the table returns `nil`. When used in a for loop, `ipairs` returns the current index and the `value` at that `index`. ```lua for index, value in ipairs(array) do @@ -106,8 +106,9 @@ end ## Length of Table Array -You can use the # operator to get the length of a table array. For tables with non-numeric indexes, you have to use pairs and calculate the length yourself, though the "length" of that kind of table isnt really useful. This follows the same rules as ipairs in the way that the table's length is every numeric index until one returns nil. So #\{1,2,3,4} will return 4, and #\{1,2,nil,4} will return 2.
-As an example, ipairs is pretty much just this. +You can use the `#` operator to get the length of a table array. For tables with non-numeric indexes, you have to use `pairs` and calculate the length yourself, though the "length" of that kind of table isnt really useful. This follows the same rules as `ipairs` in the way that the table's length is every numeric index until one returns `nil`. So `#\{1,2,3,4}` will return `4`, and `#\{1,2,nil,4}` will return `2`. + +As an example, `ipairs` is pretty much just this. ```lua for index = 1, #array, 1 do @@ -117,17 +118,18 @@ end ## Manipulating Table Arrays -Lua comes built in with ways to manipulate tables. Not all are described here, just the ones that I feel are most important.
-All of these functions are available via the tables global. +Lua comes built in with ways to manipulate tables. Not all are described here, just the ones that I feel are most important. All of these functions are available via the `tables` global. + +### `table.insert(t, pos, value)` + +This function can add a value at any index, shifting the other values to account for the added value. + +For example, `table.insert(array, 1, "e")` will insert `"e"` at the beggining of the table `array`, shifting every other value forward one index. When adding elements to the end of the array, you use the function as `table.insert(t, value)`. So `table.insert(array, "l")` appends `"l"` to the end of the table `array`. -### table.insert(t, pos, value) +### `table.remove(t, pos)` -This function can add a value at any index, shifting the other values to account for the added value.
-table.insert(array, 1, "e") will insert "e" at the beggining of the table array, shifting every other value forward one index.
-When adding elements to the end of the array, you use the function as table.insert(t, value). So table.insert(array, "l") appends "l" to the end of the table array. +This function can remove a value at any index, shifting the other values to account for the removed value. The value that was removed will be returned by this function as well. -### table.remove(t, pos) +`table.remove(array, 1)` will remove the value at index `1` from the table, shifting all the values back an index. `pos` is optional, with the default value being `#t`. -This function can remove a value at any index, shifting the other values to account for the removed value. The value that was removed will be returned by this function as well.
-table.remove(array, 1) will remove the value at index 1 from the table, shifting all the values back an index.
-pos is optional, with the default value being #t. table.remove(array) will remove the last value in the table. +`table.remove(array)` will remove the last value in the table. diff --git a/docusaurus.config.js b/docusaurus.config.js index e4541f04..edd79dfe 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -129,6 +129,16 @@ const config = { disableVersioning: true, }, ], + async function myPlugin(context, options) { + return { + name: "docusaurus-tailwindcss", + configurePostCss(postcssOptions) { + postcssOptions.plugins.push(require("tailwindcss")); + postcssOptions.plugins.push(require("autoprefixer")); + return postcssOptions; + }, + }; + }, ], webpack: { jsLoader: (isServer) => ({ diff --git a/package.json b/package.json index c3ba8f06..e18c1342 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ "clsx": "^2.0.0", "docusaurus-lunr-search": "^3.2.0", "lunr": "^2.3.9", + "medium-zoom": "^1.0.8", "prism-react-renderer": "^2.1.0", "react": "^18.2.0", "react-dom": "^18.2.0" @@ -32,8 +33,11 @@ "@prettier/plugin-lua": "^0.0.3", "@trivago/prettier-plugin-sort-imports": "^4.2.0", "@tsconfig/docusaurus": "^2.0.1", + "autoprefixer": "^10.4.16", + "postcss": "^8.4.31", "prettier": "^3.0.3", "swc-loader": "^0.2.3", + "tailwindcss": "^3.3.5", "typescript": "^5.2.2" }, "browserslist": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index bd937020..77600148 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -23,6 +23,9 @@ dependencies: lunr: specifier: ^2.3.9 version: 2.3.9 + medium-zoom: + specifier: ^1.0.8 + version: 1.0.8 prism-react-renderer: specifier: ^2.1.0 version: 2.1.0(react@18.2.0) @@ -46,12 +49,21 @@ devDependencies: '@tsconfig/docusaurus': specifier: ^2.0.1 version: 2.0.2 + autoprefixer: + specifier: ^10.4.16 + version: 10.4.16(postcss@8.4.31) + postcss: + specifier: ^8.4.31 + version: 8.4.31 prettier: specifier: ^3.0.3 version: 3.0.3 swc-loader: specifier: ^0.2.3 version: 0.2.3(@swc/core@1.3.95)(webpack@5.89.0) + tailwindcss: + specifier: ^3.3.5 + version: 3.3.5 typescript: specifier: ^5.2.2 version: 5.2.2 @@ -196,6 +208,11 @@ packages: '@algolia/requester-common': 4.20.0 dev: false + /@alloc/quick-lru@5.2.0: + resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} + engines: {node: '>=10'} + dev: true + /@ampproject/remapping@2.2.1: resolution: {integrity: sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==} engines: {node: '>=6.0.0'} @@ -2434,12 +2451,10 @@ packages: dependencies: '@nodelib/fs.stat': 2.0.5 run-parallel: 1.2.0 - dev: false /@nodelib/fs.stat@2.0.5: resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} engines: {node: '>= 8'} - dev: false /@nodelib/fs.walk@1.2.8: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} @@ -2447,7 +2462,6 @@ packages: dependencies: '@nodelib/fs.scandir': 2.1.5 fastq: 1.15.0 - dev: false /@pnpm/config.env-replace@1.1.0: resolution: {integrity: sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==} @@ -3372,13 +3386,16 @@ packages: engines: {node: '>=12'} dev: false + /any-promise@1.3.0: + resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} + dev: true + /anymatch@3.1.3: resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} engines: {node: '>= 8'} dependencies: normalize-path: 3.0.0 picomatch: 2.3.1 - dev: false /aproba@2.0.0: resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==} @@ -3386,7 +3403,6 @@ packages: /arg@5.0.2: resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} - dev: false /argparse@1.0.10: resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} @@ -3449,7 +3465,6 @@ packages: picocolors: 1.0.0 postcss: 8.4.31 postcss-value-parser: 4.2.0 - dev: false /axios@0.27.2: resolution: {integrity: sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==} @@ -3525,7 +3540,6 @@ packages: /balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - dev: false /base16@1.0.0: resolution: {integrity: sha512-pNdYkNPiJUnEhnfXV56+sQy8+AaPcG3POZAUnwr4EeqCUZFz4u2PePbo3e5Gj4ziYPCWGUZT9RHisvJKnwFuBQ==} @@ -3546,7 +3560,6 @@ packages: /binary-extensions@2.2.0: resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} engines: {node: '>=8'} - dev: false /body-parser@1.20.1: resolution: {integrity: sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==} @@ -3614,14 +3627,12 @@ packages: dependencies: balanced-match: 1.0.2 concat-map: 0.0.1 - dev: false /braces@3.0.2: resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} engines: {node: '>=8'} dependencies: fill-range: 7.0.1 - dev: false /browserslist@4.22.1: resolution: {integrity: sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==} @@ -3684,6 +3695,11 @@ packages: tslib: 2.6.2 dev: false + /camelcase-css@2.0.1: + resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} + engines: {node: '>= 6'} + dev: true + /camelcase@6.3.0: resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} engines: {node: '>=10'} @@ -3789,7 +3805,6 @@ packages: readdirp: 3.6.0 optionalDependencies: fsevents: 2.3.3 - dev: false /chrome-trace-event@1.0.3: resolution: {integrity: sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==} @@ -3908,6 +3923,11 @@ packages: /commander@2.20.3: resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} + /commander@4.1.1: + resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} + engines: {node: '>= 6'} + dev: true + /commander@5.1.0: resolution: {integrity: sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==} engines: {node: '>= 6'} @@ -3950,7 +3970,6 @@ packages: /concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - dev: false /config-chain@1.1.13: resolution: {integrity: sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==} @@ -4217,7 +4236,6 @@ packages: resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} engines: {node: '>=4'} hasBin: true - dev: false /cssnano-preset-advanced@5.3.10(postcss@8.4.31): resolution: {integrity: sha512-fnYJyCS9jgMU+cmHO1rPSPf9axbQyD7iUhLO5Df6O4G+fKIOMps+ZbU0PdGFejFBBZ3Pftf18fn1eG7MAPUSWQ==} @@ -4453,6 +4471,10 @@ packages: dequal: 2.0.3 dev: false + /didyoumean@1.2.2: + resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} + dev: true + /dir-glob@3.0.1: resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} engines: {node: '>=8'} @@ -4465,6 +4487,10 @@ packages: hasBin: true dev: false + /dlv@1.1.3: + resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} + dev: true + /dns-equal@1.0.0: resolution: {integrity: sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg==} dev: false @@ -4850,7 +4876,6 @@ packages: glob-parent: 5.1.2 merge2: 1.4.1 micromatch: 4.0.5 - dev: false /fast-json-stable-stringify@2.1.0: resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} @@ -4865,7 +4890,6 @@ packages: resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==} dependencies: reusify: 1.0.4 - dev: false /fault@2.0.1: resolution: {integrity: sha512-WtySTkS4OKev5JtpHXnib4Gxiurzh5NCGvWrFaZ34m6JehfTUhKZvn9njTfw48t6JumVQOmrKqpmGcdwxnhqBQ==} @@ -4934,7 +4958,6 @@ packages: engines: {node: '>=8'} dependencies: to-regex-range: 5.0.1 - dev: false /finalhandler@1.2.0: resolution: {integrity: sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==} @@ -5065,7 +5088,6 @@ packages: /fraction.js@4.3.7: resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} - dev: false /fresh@0.5.2: resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} @@ -5097,19 +5119,16 @@ packages: /fs.realpath@1.0.0: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - dev: false /fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] requiresBuild: true - dev: false optional: true /function-bind@1.1.2: resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - dev: false /gauge@3.0.2: resolution: {integrity: sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==} @@ -5158,18 +5177,27 @@ packages: engines: {node: '>= 6'} dependencies: is-glob: 4.0.3 - dev: false /glob-parent@6.0.2: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} dependencies: is-glob: 4.0.3 - dev: false /glob-to-regexp@0.4.1: resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} + /glob@7.1.6: + resolution: {integrity: sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + dev: true + /glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} dependencies: @@ -5320,7 +5348,6 @@ packages: engines: {node: '>= 0.4'} dependencies: function-bind: 1.1.2 - dev: false /hast-util-from-parse5@6.0.1: resolution: {integrity: sha512-jeJUWiN5pSxW12Rh01smtVkZgZr33wBokLzKLwinYOUfSzm1Nl/c3GUGebDyOKjdsRgMvoVbV0VpAcpjF4NrJA==} @@ -5750,7 +5777,6 @@ packages: dependencies: once: 1.4.0 wrappy: 1.0.2 - dev: false /inherits@2.0.3: resolution: {integrity: sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==} @@ -5758,7 +5784,6 @@ packages: /inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - dev: false /ini@1.3.8: resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} @@ -5813,7 +5838,6 @@ packages: engines: {node: '>=8'} dependencies: binary-extensions: 2.2.0 - dev: false /is-buffer@2.0.5: resolution: {integrity: sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==} @@ -5831,7 +5855,6 @@ packages: resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==} dependencies: hasown: 2.0.0 - dev: false /is-decimal@2.0.1: resolution: {integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==} @@ -5851,7 +5874,6 @@ packages: /is-extglob@2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} - dev: false /is-fullwidth-code-point@3.0.0: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} @@ -5863,7 +5885,6 @@ packages: engines: {node: '>=0.10.0'} dependencies: is-extglob: 2.1.1 - dev: false /is-hexadecimal@2.0.1: resolution: {integrity: sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==} @@ -5885,7 +5906,6 @@ packages: /is-number@7.0.0: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} - dev: false /is-obj@1.0.1: resolution: {integrity: sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==} @@ -6023,7 +6043,6 @@ packages: /jiti@1.21.0: resolution: {integrity: sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==} hasBin: true - dev: false /joi@17.11.0: resolution: {integrity: sha512-NgB+lZLNoqISVy1rZocE9PZI36bL/77ie924Ri43yEvi9GUUMPeyVIr8KdFTMUlby1p0PBYMk9spIxEUQYqrJQ==} @@ -6127,11 +6146,9 @@ packages: /lilconfig@2.1.0: resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} engines: {node: '>=10'} - dev: false /lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - dev: false /loader-runner@4.3.0: resolution: {integrity: sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==} @@ -6507,6 +6524,10 @@ packages: engines: {node: '>= 0.6'} dev: false + /medium-zoom@1.0.8: + resolution: {integrity: sha512-CjFVuFq/IfrdqesAXfg+hzlDKu6A2n80ZIq0Kl9kWjoHh9j1N9Uvk5X0/MmN0hOfm5F9YBswlClhcwnmtwz7gA==} + dev: false + /memfs@3.5.3: resolution: {integrity: sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==} engines: {node: '>= 4.0.0'} @@ -6524,7 +6545,6 @@ packages: /merge2@1.4.1: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} - dev: false /methods@1.1.2: resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} @@ -6914,7 +6934,6 @@ packages: dependencies: braces: 3.0.2 picomatch: 2.3.1 - dev: false /mime-db@1.33.0: resolution: {integrity: sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==} @@ -6977,7 +6996,6 @@ packages: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} dependencies: brace-expansion: 1.1.11 - dev: false /minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} @@ -7012,11 +7030,18 @@ packages: thunky: 1.1.0 dev: false + /mz@2.7.0: + resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} + dependencies: + any-promise: 1.3.0 + object-assign: 4.1.1 + thenify-all: 1.6.0 + dev: true + /nanoid@3.3.6: resolution: {integrity: sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true - dev: false /negotiator@0.6.3: resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} @@ -7072,12 +7097,10 @@ packages: /normalize-path@3.0.0: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} - dev: false /normalize-range@0.1.2: resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==} engines: {node: '>=0.10.0'} - dev: false /normalize-url@6.1.0: resolution: {integrity: sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==} @@ -7114,6 +7137,11 @@ packages: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} + /object-hash@3.0.0: + resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} + engines: {node: '>= 6'} + dev: true + /object-inspect@1.13.1: resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==} dev: false @@ -7153,7 +7181,6 @@ packages: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} dependencies: wrappy: 1.0.2 - dev: false /onetime@5.1.2: resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} @@ -7341,7 +7368,6 @@ packages: /path-is-absolute@1.0.1: resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} engines: {node: '>=0.10.0'} - dev: false /path-is-inside@1.0.2: resolution: {integrity: sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w==} @@ -7354,7 +7380,6 @@ packages: /path-parse@1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - dev: false /path-to-regexp@0.1.7: resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==} @@ -7389,7 +7414,16 @@ packages: /picomatch@2.3.1: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} - dev: false + + /pify@2.3.0: + resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} + engines: {node: '>=0.10.0'} + dev: true + + /pirates@4.0.6: + resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} + engines: {node: '>= 6'} + dev: true /pkg-dir@7.0.0: resolution: {integrity: sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA==} @@ -7485,6 +7519,45 @@ packages: postcss-selector-parser: 6.0.13 dev: false + /postcss-import@15.1.0(postcss@8.4.31): + resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==} + engines: {node: '>=14.0.0'} + peerDependencies: + postcss: ^8.0.0 + dependencies: + postcss: 8.4.31 + postcss-value-parser: 4.2.0 + read-cache: 1.0.0 + resolve: 1.22.8 + dev: true + + /postcss-js@4.0.1(postcss@8.4.31): + resolution: {integrity: sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==} + engines: {node: ^12 || ^14 || >= 16} + peerDependencies: + postcss: ^8.4.21 + dependencies: + camelcase-css: 2.0.1 + postcss: 8.4.31 + dev: true + + /postcss-load-config@4.0.1(postcss@8.4.31): + resolution: {integrity: sha512-vEJIc8RdiBRu3oRAI0ymerOn+7rPuMvRXslTvZUKZonDHFIczxztIyJ1urxM1x9JXEikvpWWTUUqal5j/8QgvA==} + engines: {node: '>= 14'} + peerDependencies: + postcss: '>=8.0.9' + ts-node: '>=9.0.0' + peerDependenciesMeta: + postcss: + optional: true + ts-node: + optional: true + dependencies: + lilconfig: 2.1.0 + postcss: 8.4.31 + yaml: 2.3.4 + dev: true + /postcss-loader@7.3.3(postcss@8.4.31)(typescript@5.2.2)(webpack@5.89.0): resolution: {integrity: sha512-YgO/yhtevGO/vJePCQmTxiaEwER94LABZN0ZMT4A0vsak9TpO+RvKRs7EmJ8peIlB9xfXCsS7M8LjqncsUZ5HA==} engines: {node: '>= 14.15.0'} @@ -7621,6 +7694,16 @@ packages: postcss: 8.4.31 dev: false + /postcss-nested@6.0.1(postcss@8.4.31): + resolution: {integrity: sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==} + engines: {node: '>=12.0'} + peerDependencies: + postcss: ^8.2.14 + dependencies: + postcss: 8.4.31 + postcss-selector-parser: 6.0.13 + dev: true + /postcss-normalize-charset@5.1.0(postcss@8.4.31): resolution: {integrity: sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==} engines: {node: ^10 || ^12 || >=14.0} @@ -7760,7 +7843,6 @@ packages: dependencies: cssesc: 3.0.0 util-deprecate: 1.0.2 - dev: false /postcss-sort-media-queries@4.4.1(postcss@8.4.31): resolution: {integrity: sha512-QDESFzDDGKgpiIh4GYXsSy6sek2yAwQx1JASl5AxBtU1Lq2JfKBljIPNdil989NcSKRQX1ToiaKphImtBuhXWw==} @@ -7795,7 +7877,6 @@ packages: /postcss-value-parser@4.2.0: resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} - dev: false /postcss-zindex@5.1.0(postcss@8.4.31): resolution: {integrity: sha512-fgFMf0OtVSBR1va1JNHYgMxYk73yhn/qb4uQDq1DLGYolz8gHCyr/sesEuGUaYs58E3ZJRcpoGuPVoB7Meiq9A==} @@ -7813,7 +7894,6 @@ packages: nanoid: 3.3.6 picocolors: 1.0.0 source-map-js: 1.0.2 - dev: false /prettier@3.0.3: resolution: {integrity: sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==} @@ -7923,7 +8003,6 @@ packages: /queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - dev: false /queue@6.0.2: resolution: {integrity: sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==} @@ -8134,6 +8213,12 @@ packages: dependencies: loose-envify: 1.4.0 + /read-cache@1.0.0: + resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==} + dependencies: + pify: 2.3.0 + dev: true + /readable-stream@2.3.8: resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} dependencies: @@ -8160,7 +8245,6 @@ packages: engines: {node: '>=8.10.0'} dependencies: picomatch: 2.3.1 - dev: false /reading-time@1.5.0: resolution: {integrity: sha512-onYyVhBNr4CmAxFsKS7bz+uTLRakypIe4R+5A824vBSkQy/hB3fZepoVEf8OVAxzLvK+H/jm9TzpI3ETSm64Kg==} @@ -8385,7 +8469,6 @@ packages: is-core-module: 2.13.1 path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 - dev: false /responselike@3.0.0: resolution: {integrity: sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==} @@ -8402,7 +8485,6 @@ packages: /reusify@1.0.4: resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - dev: false /rimraf@3.0.2: resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} @@ -8430,7 +8512,6 @@ packages: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} dependencies: queue-microtask: 1.2.3 - dev: false /rxjs@7.8.1: resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==} @@ -8721,7 +8802,6 @@ packages: /source-map-js@1.0.2: resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} engines: {node: '>=0.10.0'} - dev: false /source-map-support@0.5.21: resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} @@ -8902,6 +8982,20 @@ packages: postcss-selector-parser: 6.0.13 dev: false + /sucrase@3.34.0: + resolution: {integrity: sha512-70/LQEZ07TEcxiU2dz51FKaE6hCTWC6vr7FOk3Gr0U60C3shtAN+H+BFr9XlYe5xqf3RA8nrc+VIwzCfnxuXJw==} + engines: {node: '>=8'} + hasBin: true + dependencies: + '@jridgewell/gen-mapping': 0.3.3 + commander: 4.1.1 + glob: 7.1.6 + lines-and-columns: 1.2.4 + mz: 2.7.0 + pirates: 4.0.6 + ts-interface-checker: 0.1.13 + dev: true + /supports-color@5.5.0: resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} engines: {node: '>=4'} @@ -8924,7 +9018,6 @@ packages: /supports-preserve-symlinks-flag@1.0.0: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} - dev: false /svg-parser@2.0.4: resolution: {integrity: sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==} @@ -8954,6 +9047,37 @@ packages: webpack: 5.89.0(@swc/core@1.3.95) dev: true + /tailwindcss@3.3.5: + resolution: {integrity: sha512-5SEZU4J7pxZgSkv7FP1zY8i2TIAOooNZ1e/OGtxIEv6GltpoiXUqWvLy89+a10qYTB1N5Ifkuw9lqQkN9sscvA==} + engines: {node: '>=14.0.0'} + hasBin: true + dependencies: + '@alloc/quick-lru': 5.2.0 + arg: 5.0.2 + chokidar: 3.5.3 + didyoumean: 1.2.2 + dlv: 1.1.3 + fast-glob: 3.3.1 + glob-parent: 6.0.2 + is-glob: 4.0.3 + jiti: 1.21.0 + lilconfig: 2.1.0 + micromatch: 4.0.5 + normalize-path: 3.0.0 + object-hash: 3.0.0 + picocolors: 1.0.0 + postcss: 8.4.31 + postcss-import: 15.1.0(postcss@8.4.31) + postcss-js: 4.0.1(postcss@8.4.31) + postcss-load-config: 4.0.1(postcss@8.4.31) + postcss-nested: 6.0.1(postcss@8.4.31) + postcss-selector-parser: 6.0.13 + resolve: 1.22.8 + sucrase: 3.34.0 + transitivePeerDependencies: + - ts-node + dev: true + /tapable@1.1.3: resolution: {integrity: sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==} engines: {node: '>=6'} @@ -9001,6 +9125,19 @@ packages: resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} dev: false + /thenify-all@1.6.0: + resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} + engines: {node: '>=0.8'} + dependencies: + thenify: 3.3.1 + dev: true + + /thenify@3.3.1: + resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} + dependencies: + any-promise: 1.3.0 + dev: true + /thunky@1.1.0: resolution: {integrity: sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==} dev: false @@ -9022,7 +9159,6 @@ packages: engines: {node: '>=8.0'} dependencies: is-number: 7.0.0 - dev: false /to-vfile@6.1.0: resolution: {integrity: sha512-BxX8EkCxOAZe+D/ToHdDsJcVI4HqQfmw0tCkp31zf3dNP/XWIAjU4CmeuSwsSoOzOTqHPOL0KUzyZqJplkD0Qw==} @@ -9057,6 +9193,10 @@ packages: resolution: {integrity: sha512-AqTiAOLcj85xS7vQ8QkAV41hPDIJ71XJB4RCUrzo/1GM2CQwhkJGaf9Hgr7BOugMRpgGUrqRg/DrBDl4H40+8g==} dev: false + /ts-interface-checker@0.1.13: + resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} + dev: true + /tslib@2.6.2: resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} dev: false @@ -9332,7 +9472,6 @@ packages: /util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - dev: false /utila@0.4.0: resolution: {integrity: sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==} @@ -9661,7 +9800,6 @@ packages: /wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - dev: false /write-file-atomic@3.0.3: resolution: {integrity: sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==} @@ -9728,6 +9866,11 @@ packages: engines: {node: '>= 6'} dev: false + /yaml@2.3.4: + resolution: {integrity: sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==} + engines: {node: '>= 14'} + dev: true + /yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} diff --git a/src/components/Image.tsx b/src/components/Image.tsx new file mode 100644 index 00000000..9039cd62 --- /dev/null +++ b/src/components/Image.tsx @@ -0,0 +1,56 @@ +import mediumZoom, { Zoom } from "medium-zoom"; +import React, { FC, PropsWithChildren } from "react"; + +export type ImageProps = PropsWithChildren<{ + src: string; + alt?: string; + + width?: string | number; + + className?: string; +}>; + +const Image: FC = ({ src, alt, className, width, children }) => { + const path: string | undefined = src.startsWith("/") ? require("@site/static" + src)?.default : src; + const zoomRef = React.useRef(null); + + const getZoom = () => { + if (zoomRef.current === null) { + zoomRef.current = mediumZoom({ + background: "rgba(0, 0, 0, 0.65)", + }); + } + + return zoomRef.current; + }; + + const attachZoom = (image: HTMLImageElement | null) => { + const zoom = getZoom(); + + if (image) { + zoom.attach(image); + } else { + zoom.detach(); + } + }; + + return ( +
+
+ {alt} +
+ {children && ( +
+ {children} +
+ )} +
+ ); +}; + +export default Image; diff --git a/src/css/custom.css b/src/css/custom.css index 7b51952e..56fc6181 100644 --- a/src/css/custom.css +++ b/src/css/custom.css @@ -4,6 +4,10 @@ * work well for content-centric websites. */ + @tailwind base; + @tailwind components; + @tailwind utilities; + /* You can override the default Infima variables here. */ :root { --ifm-color-primary: #2e8555; @@ -55,3 +59,7 @@ background-color: #ff000020; border-left-color: #ff000080; } + +figcaption :last-child { + margin-bottom: 0; +} \ No newline at end of file diff --git a/static/img/animation/exampleBbmodel.png b/static/img/animation/exampleBbmodel.png deleted file mode 100644 index ef36e93e..00000000 Binary files a/static/img/animation/exampleBbmodel.png and /dev/null differ diff --git a/tailwind.config.js b/tailwind.config.js new file mode 100644 index 00000000..5cf99c8a --- /dev/null +++ b/tailwind.config.js @@ -0,0 +1,12 @@ +/** @type {import('tailwindcss').Config} */ +module.exports = { + corePlugins: { + preflight: false, + }, + content: ["./src/**/*.{js,jsx,ts,tsx}", "./docs/**/*.{md,mdx}"], + darkMode: ["class", '[data-theme="dark"]'], + theme: { + extend: {}, + }, + plugins: [], +};