aboutsummaryrefslogtreecommitdiff
path: root/web/src/pages
diff options
context:
space:
mode:
Diffstat (limited to 'web/src/pages')
-rw-r--r--web/src/pages/docs/_texture-pack-format.md350
-rw-r--r--web/src/pages/docs/texture-pack-format.astro1
-rw-r--r--web/src/pages/index.astro2
-rw-r--r--web/src/pages/texture-packs.astro1
4 files changed, 350 insertions, 4 deletions
diff --git a/web/src/pages/docs/_texture-pack-format.md b/web/src/pages/docs/_texture-pack-format.md
index da66043..8cbedbf 100644
--- a/web/src/pages/docs/_texture-pack-format.md
+++ b/web/src/pages/docs/_texture-pack-format.md
@@ -139,11 +139,31 @@ Filter by item type:
"firmament:item": "minecraft:clock"
```
+#### Skulls
+
+You can match skulls using the skull textures and other properties using the skull predicate. If there are no properties specified this is equivalent to checking if the item is a `minecraft:player_head`.
+
+```json
+"firmament:skull": {
+ "profileId": "cca2d452-c6d3-39cb-b695-5ec92b2d6729",
+ "textureProfileId": "1d5233d388624bafb00e3150a7aa3a89",
+ "skinUrl": "http://textures.minecraft.net/texture/7bf01c198f6e16965e230235cd22a5a9f4a40e40941234478948ff9a56e51775",
+ "textureValue": "ewogICJ0aW1lc3RhbXAiIDogMTYxODUyMTY2MzY1NCwKICAicHJvZmlsZUlkIiA6ICIxZDUyMzNkMzg4NjI0YmFmYjAwZTMxNTBhN2FhM2E4OSIsCiAgInByb2ZpbGVOYW1lIiA6ICIwMDAwMDAwMDAwMDAwMDBKIiwKICAic2lnbmF0dXJlUmVxdWlyZWQiIDogdHJ1ZSwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzdiZjAxYzE5OGY2ZTE2OTY1ZTIzMDIzNWNkMjJhNWE5ZjRhNDBlNDA5NDEyMzQ0Nzg5NDhmZjlhNTZlNTE3NzUiLAogICAgICAibWV0YWRhdGEiIDogewogICAgICAgICJtb2RlbCIgOiAic2xpbSIKICAgICAgfQogICAgfQogIH0KfQ"
+}
+```
+
+| Name | Type | Description |
+|--------------------|---------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| `profileId` | UUID | Match the uuid of the profile component directly. |
+| `textureProfileId` | UUID | Match the uuid of the skin owner in the encoded texture value. This is more expensive, but can deviate from the profile id of the profile owner. |
+| `skinUrl` | [string](#string-matcher) | Match the texture url of the skin. This starts with `http://`, not with `https:/` in most cases. |
+| `textureValue` | [string](#string-matcher) | Match the texture value. This is the encoded base64 string of the texture url along with metadata. It is faster to query than the `skinUrl`, but it can out of changed without causing any semantic changes, and is less readable than the skinUrl. |
+
#### Extra attributes
Filter by extra attribute NBT data:
-Specify a `path` to look at, separating sub elements with a `.`. You can use a `*` to check any child.
+Specify a `path` (using an [nbt prism](#nbt-prism)) to look at, separating sub elements with a `.`. You can use a `*` to check any child.
Then either specify a `match` sub-object or directly inline that object in the format of an [nbt matcher](#nbt-matcher).
@@ -167,6 +187,32 @@ Sub object match:
}
```
+#### Components
+
+You can match generic components similarly to [extra attributes](#extra-attributes). If you want to match an extra
+attribute match directly using that, for better performance.
+
+You can specify a `path` (using an [nbt prism](#nbt-prism)) and match similar to extra attributes, but in addition you can also specify a `component`. This
+variable is the identifier of a component type that will then be encoded to nbt and matched according to the `match`
+using a [nbt matcher](#nbt-matcher).
+
+```json5
+"firmament:component": {
+ "path": "rgb",
+ "component": "minecraft:dyed_color",
+ "int": 255
+}
+// Alternatively
+"firmament:component": {
+ "path": "rgb",
+ "component": "minecraft:dyed_color",
+ "match": {
+ "int": 255
+ }
+}
+```
+
+
#### Pet Data
Filter by pet information. While you can already filter by the skyblock id for pet type and tier, this allows you to
@@ -310,6 +356,58 @@ compare your number:
This example would match if the level is less than fifty. The available operators are `<`, `>`, `<=` and `>=`. The
operator needs to be specified on the left. The versions of the operator with `=` also allow the number to be equal.
+### Nbt Prism
+
+An nbt prism (or path) is used to specify where in a complex nbt construct to look for a value. A basic prism just looks
+like a dot-separated path (`parent.child.grandchild`), but more complex paths can be constructed.
+
+First the specified path is split into dot separated chunks: `"a.b.c"` -> `["a", "b", "c"]`. You can also directly
+specify the list if you would like. Any entry in that list not starting with a `*` is treated as an attribute name or
+an index:
+
+```json
+{
+ "propA": {
+ "propB": {
+ "propC": 100,
+ "propD": 1000
+ }
+ },
+ "someOtherProp": "hello",
+ "someThirdProp": "{\"innerProp\": true}",
+ "someFourthProp": "aGlkZGVuIHZhbHVl"
+}
+```
+
+In this example json (which is supposed to represent a corresponding nbt object), you can use a path like
+`propA.propB.propC` to directly extract the value `100`.
+
+If you want to extract all of the innermost values of `propB`
+(for example if `propB` was an array instead), you could use `propA.propB.*`. You can use the `*` at any level:
+`*.*.*` for example extracts all properties that are exactly at the third level. In that case you would try to match any
+of the values of `[100, 1000]` to your match object.
+
+Sometimes values are encoded in a non-nbt format inside a string. For those you can use other star based directives like
+`*base64` or `*json` to decode those entries.
+
+`*base64` turns a base64 encoded string into the base64 decoded counterpart. `*json` decodes a string into the json
+object represented by that string. Note that json to nbt conversion isn't always straightforwards and the types can
+end up being mangled (for example what could have been a byte ends up an int).
+
+| Path | Result |
+|---------------------------------|---------------------------------|
+| `propA.propB` | `{"propC": 100, "propD": 1000}` |
+| `propA.propB.propC` | `100` |
+| `propA.*.propC` | `100` |
+| `propA.propB.*` | `100`, `1000` |
+| `someOtherProp` | `"hello"` |
+| `someThirdProp` | "{\"innerProp\": true}" |
+| `someThirdProp.*json` | {"innerProp": true} |
+| `someThirdProp.*json.innerProp` | true |
+| `someFourthProp` | `"aGlkZGVuIHZhbHVl"` |
+| `someFourthProp.*base64` | `"hidden value"` |
+
+
### Nbt Matcher
This matches a single nbt element.
@@ -477,6 +575,251 @@ not screens from other mods. You can also target specific texts via a [string ma
| `overrides.predicate` | true | This is a [string matcher](#string-matcher) that allows you to match on the text you are replacing |
| `overrides.override` | true | This is the replacement color that will be used if the predicate matches. |
+## Screen Layout Replacement
+
+You can change the layout of an entire screen by using screen layout overrides. These get placed in `firmskyblock:overrides/screen_layout/*.json`, with one file per screen. You can match on the title of a screen, the type of screen, replace the background texture (including extending the background canvas further than vanilla allows you) and move slots around.
+
+### Selecting a screen
+
+```json
+{
+ "predicates": {
+ "label": {
+ "regex": "Hyper Furnace"
+ },
+ "screenType": "minecraft:furnace"
+ }
+}
+```
+
+The `label` property is a regular [string matcher](#string-matcher) and matches against the screens title (typically the chest title, or "Crafting" for the players inventory).
+
+The `screenType` property is an optional namespaced identifier that allows matching to a [screen type](https://minecraft.wiki/w/Java_Edition_protocol/Inventory#Types).
+
+Signs can be targeted using `firmskyblock:sign` and `firmskyblock:hanging_sign`.
+
+### Changing the background
+
+```json
+{
+ "predicates": {
+ "label": {
+ "regex": "Hyper Furnace"
+ }
+ },
+ "background": {
+ "texture": "firmskyblock:textures/furnace.png",
+ "x": -21,
+ "y": -30,
+ "width": 197,
+ "height": 196
+ }
+}
+```
+
+You need to specify an x and y offset relative to where the regular screen would render. This means you just check where the upper left corner of the UI texture would be in your texture (and turn it into a negative number). You also need to specify a width and height of your texture. This is the width in pixels rendered. If you want a higher or lower resolution texture, you can scale the actual texture up (tho it is expected to meet the same aspect ratio as the one defined here).
+
+Signs do not have a regular origin and are instead anchored from the top-middle of the sign.
+
+### Moving slots around
+
+```json
+{
+ "predicates": {
+ "label": {
+ "regex": "Hyper Furnace"
+ }
+ },
+ "slots": [
+ {
+ "index": 10,
+ "x": -5000,
+ "y": -5000
+ }
+ ]
+}
+```
+
+You can move slots around by a specific index. This is not the index in the inventory, but rather the index in the screen (so if you have a chest screen then all the player inventory slots would be a higher index since the chest slots move them down the list). The x and y are relative to where the regular screen top left would be. Set to large values to effectively "delete" a slot by moving it offscreen.
+
+### Moving text around
+
+```json
+{
+ "predicates": {
+ "label": {
+ "regex": "Hyper Furnace"
+ }
+ },
+ "playerTitle": {
+ "x": 0,
+ "y": 0,
+ "align": "left",
+ "replace": "a"
+ }
+}
+```
+
+You can move the window title around. The x and y are relative to the top left of the regular screen (like slots). Set to large values to effectively "delete" a slot by moving it offscreen.
+
+The align only specifies the direction the text grows in, it does not the actual anchor point, so if you want right aligned text you will also need to move the origin of the text to the right (or it will just grow out of the left side of your screen).
+
+You can replace the text with another text to render instead.
+
+Available titles are
+
+- `containerTitle` for the title of the open container, typically at the very top.
+- `playerTitle` for the players inventory title. Note that in the player inventory without a chest or something open, the `containerTitle` is also used for the "Crafting" text.
+- `repairCostTitle` for the repair cost label in anvils.
+
+### Moving components around
+
+```json
+{
+ "predicates": {
+ "label": {
+ "regex": "Hyper Furnace"
+ }
+ },
+ "nameField": {
+ "x": 10,
+ "y": 10,
+ "width": 100,
+ "height": 12
+ }
+}
+```
+
+Some other components can also be moved. These components might be buttons, text inputs or other things not fitting into any category. They can have a x, y (relative to the top left of the screen), as well as sometimes a width, height, and other properties. This is more of a wild card category, and which options work depends on the type of object.
+
+Available options
+
+- `nameField`: x, y, width & height are all available to move the field to set the name of the item in an anvil.
+- `signLines[]`: x, y, are available to move the text relative to where it would render normally. Must be an array of 4 component movers.
+
+### All together
+
+| Field | Required | Description |
+|---------------------------|----------|--------------------------------------------------------------------------------------------------------------------------|
+| `predicates` | true | A list of predicates that need to match in order to change the layout of a screen |
+| `predicates.label` | true | A [string matcher](#string-matcher) for the screen title |
+| `background` | false | Allows replacing the background texture |
+| `background.texture` | true | The texture of the background as an identifier |
+| `background.x` | true | The x offset of the background relative to where the regular background would be rendered. |
+| `background.y` | true | The y offset of the background relative to where the regular background would be rendered. |
+| `background.width` | true | The width of the background texture. |
+| `background.height` | true | The height of the background texture. |
+| `slots` | false | An array of slots to move around. |
+| `slots[*].index` | true | The index in the array of all slots on the screen (not inventory). |
+| `slots[*].x` | true | The x coordinate of the slot relative to the top left of the screen |
+| `slots[*].y` | true | The y coordinate of the slot relative to the top left of the screen |
+| `<element>Title` | false | The title mover (see above for valid options) |
+| `<element>Title.x` | false | The x coordinate of text relative to the top left of the screen |
+| `<element>Title.y` | false | The y coordinate of text relative to the top left of the screen |
+| `<element>Title.align` | false | How you want the text to align. "left", "center" or "right". This only changes the text direction, not its anchor point. |
+| `<element>Title.replace` | false | Replace the text with your own text |
+| `<extraComponent>` | false | Allows you to move button components and similar around |
+| `<extraComponent>.x` | true | The new x coordinate of the component relative to the top left of the screen |
+| `<extraComponent>.x` | true | The new y coordinate of the component relative to the top left of the screen |
+| `<extraComponent>.width` | false | The new width of the component |
+| `<extraComponent>.height` | false | The new height of the component |
+
+## Text Replacements
+
+> [!WARNING]
+> This syntax is _experimental_ and may be reworked with no backwards compatibility guarantees. If you have a use case for this syntax, please contact me so that I can figure out what kind of features are needed for the final version of this API.
+
+Firmament allows you to replace arbitrary texts with other texts during rendering. This only affects rendering, not what other mods see.
+
+To do this, place a text override in `firmskyblock:overrides/texts/<my-override>.json`:
+
+```json
+{
+ "match": {
+ "regex": ".*Strength.*"
+ },
+ "replacements": [
+ {
+ "match": "❁",
+ "replace": {
+ "text": "<newIcon>",
+ "color": "#ff0000"
+ }
+ }
+ ]
+}
+```
+
+There are notably two separate "match" sections. This is important. The first (top-level) match checks against the entire text element, while the replacement match operates on each individual subcomponent. Let's look at an example:
+
+```json
+{
+ "italic": false,
+ "text": "",
+ "extra": [
+ " ",
+ {
+ "color": "red",
+ "text": "❁ Strength "
+ },
+ {
+ "color": "white",
+ "text": "510.45"
+ }
+ ]
+}
+```
+
+In this the entire text rendered out looks like `" ❁ Strength 510.45"` and the top-level match (`".*Strength.*"`) needs to match that line.
+
+Then each replacement (in the `replacements` array) is matched against each subcomponent.
+First, it tries to find `"❁"` in the empty root element `""`. Then it tries the first child (`" "`) and fails again. Then it tries the `"❁ Strength "` component and finds one match. It then splits the `"❁ Strength "` component into multiple subsubcomponents and replaces just the `❁` part with the one specified in the replacements array. Afterwards, it fails to match the `"510.45"` component and returns.
+
+Our finalized text looks like this:
+
+```json
+{
+ "italic": false,
+ "text": "",
+ "extra": [
+ " ",
+ {
+ "color": "red",
+ "text": "",
+ "extra": [
+ {
+ "text": "<newIcon>",
+ "color": "#ff0000"
+ },
+ " Strength "
+ ]
+ },
+ {
+ "color": "white",
+ "text": "510.45"
+ }
+ ]
+}
+```
+
+Which rendered out looks like ` <newIcon> Strength 510.45`, with all colours original, except the `<newIcon>` which not only has new text but also a new colour.
+
+| Field | Required | Description |
+|--------------------------------------|----------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| `match` | yes | A top level [string matcher](#string-matcher). Allows for testing parts of the text unrelated to the replacement and improves performance. |
+| `replacements` | yes | A list of replacements to apply to each part of the text |
+| `replacements.*.match` | yes | A [string matcher](#string-matcher) substring to replace in each component of the text. Notabene: Unlike most string matchers, this one is not anchored to the beginning and end of the element, so if the entire component needs to be matched a regex with `^$` needs to be used. |
+| `replacements.*.style` | yes | A vanilla [style](https://minecraft.wiki/w/Text_component_format#Java_Edition) (where only the fields `color`, `italic`, `bold`, `underlined`, `strikethrough` and `obfuscated` are set). Checks if this specific subcomponent is of the correct style |
+| `replacements.*.style.color` | no | A vanilla color name (as set in a text) that checks that the subcomponent is of that colour. |
+| `replacements.*.style.italic` | no | A boolean that can be set `true` or `false` to require this text to be italic or not. |
+| `replacements.*.style.bold` | no | A boolean that can be set `true` or `false` to require this text to be bold or not. |
+| `replacements.*.style.underlined` | no | A boolean that can be set `true` or `false` to require this text to be underlined or not. |
+| `replacements.*.style.strikethrough` | no | A boolean that can be set `true` or `false` to require this text to be strikethrough or not. |
+| `replacements.*.style.obfuscated` | no | A boolean that can be set `true` or `false` to require this text to be obfuscated or not. |
+| `replacements.*.replace` | yes | A vanilla [text](https://minecraft.wiki/w/Text_component_format#Java_Edition) that is inserted to replace the substring matched in the match. If literal texts (not translated texts) are used, then `${name}` can be used to access named groups in the match regex (if a regex matcher was used). |
+
+
+
## Global Item Texture Replacement
Most texture replacement is done based on the SkyBlock id of the item. However, some items you might want to re-texture
@@ -565,6 +908,11 @@ which block models are replaced under which conditions:
}
```
+The referenced `block` can either be a regular json block model (like the ones in `assets/minecraft/blocks/`), or it can
+reference a blockstates json like in `assets/<namespace>/blockstates/<path>.json`. The blockstates.json is prefered and
+needs to match the vanilla format, so it is best to copy over the vanilla blockstates.json for the block you are editing
+and replace all block model paths with your own custom block models.
+
| Field | Required | Description |
|-------------------------|----------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `modes` | yes | A list of `/locraw` mode names. |
diff --git a/web/src/pages/docs/texture-pack-format.astro b/web/src/pages/docs/texture-pack-format.astro
index 0714aea..ed14cde 100644
--- a/web/src/pages/docs/texture-pack-format.astro
+++ b/web/src/pages/docs/texture-pack-format.astro
@@ -6,7 +6,6 @@ import MarkDown from './_texture-pack-format.md';
---
<Base title="Firmament Texture Packs">
- <NavBar></NavBar>
<Content>
<MarkDown/>
</Content>
diff --git a/web/src/pages/index.astro b/web/src/pages/index.astro
index 4baa867..f8c789f 100644
--- a/web/src/pages/index.astro
+++ b/web/src/pages/index.astro
@@ -6,7 +6,7 @@ import NavBar from "../components/NavBar.astro";
import Content from "../layouts/Content.astro";
---
-<Base title="Firmament">
+<Base title="Firmament" navbar={false}>
<Hero image={Image} alt="A panorama shot of the HyPixel SkyBlock hub">
<h1 class="text-4xl font-bold leading-tight mb-4">Firmament</h1>
<p class="text-lg text-gray-300 mb-8">Hypixel SkyBlock Utility Mod</p>
diff --git a/web/src/pages/texture-packs.astro b/web/src/pages/texture-packs.astro
index ee511f9..0f34157 100644
--- a/web/src/pages/texture-packs.astro
+++ b/web/src/pages/texture-packs.astro
@@ -4,6 +4,5 @@ import NavBar from "../components/NavBar.astro";
---
<Base title="Firmament Texture Packs">
- <NavBar></NavBar>
</Base>