Add custom inventory text color texture pack support
This commit is contained in:
@@ -12,7 +12,8 @@ Find the internal id of the item. This is usually stored in the ExtraAttributes
|
||||
keybinds). Once you found it, create an item model in a resource pack like you would for
|
||||
a vanilla item model, but at the coordinate `firmskyblock:<internalid>`. So for an aspect of the end, this would be
|
||||
`firmskyblock:models/item/aspect_of_the_end.json` (or `assets/firmskyblock/models/item/aspect_of_the_end.json`). Then,
|
||||
just use a normal minecraft item model. See https://github.com/romangraef/BadSkyblockTP/blob/master/assets/firmskyblock/models/item/magma_rod.json
|
||||
just use a normal minecraft item model.
|
||||
See https://github.com/romangraef/BadSkyblockTP/blob/master/assets/firmskyblock/models/item/magma_rod.json
|
||||
as an example.
|
||||
|
||||
## (Placed) Skulls by texture id
|
||||
@@ -32,18 +33,21 @@ head model.
|
||||
|
||||
```json5
|
||||
{
|
||||
"parent": "minecraft:item/generated",
|
||||
"textures": {
|
||||
"layer0": "firmskyblock:item/regular_texture"
|
||||
},
|
||||
"firmament:head_model": "minecraft:block/diamond_block" // when wearing on the head render a diamond block instead (can be any item model, including custom ones)
|
||||
"parent": "minecraft:item/generated",
|
||||
"textures": {
|
||||
"layer0": "firmskyblock:item/regular_texture"
|
||||
},
|
||||
"firmament:head_model": "minecraft:block/diamond_block"
|
||||
// when wearing on the head render a diamond block instead (can be any item model, including custom ones)
|
||||
}
|
||||
```
|
||||
|
||||
## Predicates
|
||||
|
||||
Firmament adds the ability for more complex [item model predicates](https://minecraft.wiki/w/Tutorials/Models#Item_predicates).
|
||||
Those predicates work on any model, including models for vanilla items, but they don't mix very well with vanilla model overrides.
|
||||
Firmament adds the ability for more
|
||||
complex [item model predicates](https://minecraft.wiki/w/Tutorials/Models#Item_predicates).
|
||||
Those predicates work on any model, including models for vanilla items, but they don't mix very well with vanilla model
|
||||
overrides.
|
||||
Vanilla predicates only ever get parsed at the top level, so including a vanilla predicate inside of a more complex
|
||||
firmament parser will result in an ignored predicate.
|
||||
|
||||
@@ -51,21 +55,21 @@ firmament parser will result in an ignored predicate.
|
||||
|
||||
```json
|
||||
{
|
||||
"parent": "minecraft:item/handheld",
|
||||
"textures": {
|
||||
"layer0": "firmskyblock:item/bat_wand"
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"predicate": {
|
||||
"firmament:display_name": {
|
||||
"regex": ".*§d.*",
|
||||
"color": "preserve"
|
||||
}
|
||||
},
|
||||
"model": "firmskyblock:item/recombobulated_bat_wand"
|
||||
}
|
||||
]
|
||||
"parent": "minecraft:item/handheld",
|
||||
"textures": {
|
||||
"layer0": "firmskyblock:item/bat_wand"
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"predicate": {
|
||||
"firmament:display_name": {
|
||||
"regex": ".*§d.*",
|
||||
"color": "preserve"
|
||||
}
|
||||
},
|
||||
"model": "firmskyblock:item/recombobulated_bat_wand"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
@@ -89,8 +93,8 @@ Tries to find at least one lore line that matches the given [string matcher](#st
|
||||
|
||||
```json
|
||||
"firmament:lore": {
|
||||
"regex": "Mode: Red Mushrooms",
|
||||
"color": "strip"
|
||||
"regex": "Mode: Red Mushrooms",
|
||||
"color": "strip"
|
||||
}
|
||||
```
|
||||
|
||||
@@ -114,8 +118,8 @@ Inlined match:
|
||||
|
||||
```json5
|
||||
"firmament:extra_attributes": {
|
||||
"path": "gems.JADE_0",
|
||||
"string": "PERFECT"
|
||||
"path": "gems.JADE_0",
|
||||
"string": "PERFECT"
|
||||
}
|
||||
```
|
||||
|
||||
@@ -123,10 +127,10 @@ Sub object match:
|
||||
|
||||
```json5
|
||||
"firmament:extra_attributes": {
|
||||
"path": "gems.JADE_0",
|
||||
"match": {
|
||||
"string": "PERFECT"
|
||||
}
|
||||
"path": "gems.JADE_0",
|
||||
"match": {
|
||||
"string": "PERFECT"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -137,11 +141,11 @@ further filter by level and some other pet info.
|
||||
|
||||
```json5
|
||||
"firmament:pet" {
|
||||
"id": "WOLF",
|
||||
"exp": ">=25353230",
|
||||
"tier": "[RARE,LEGENDARY]",
|
||||
"level": "[50,)",
|
||||
"candyUsed": 0
|
||||
"id": "WOLF",
|
||||
"exp": ">=25353230",
|
||||
"tier": "[RARE,LEGENDARY]",
|
||||
"level": "[50,)",
|
||||
"candyUsed": 0
|
||||
}
|
||||
```
|
||||
|
||||
@@ -155,24 +159,24 @@ further filter by level and some other pet info.
|
||||
|
||||
Every part of this matcher is optional.
|
||||
|
||||
|
||||
#### Logic Operators
|
||||
|
||||
Logic operators allow to combine other firmament predicates into one. This is done by building boolean operators:
|
||||
|
||||
```json5
|
||||
"firmament:any": [
|
||||
{
|
||||
"firmament:display_name": "SkyBlock Menu (Click)"
|
||||
},
|
||||
{
|
||||
"firmament:display_name": "SkyBlock",
|
||||
"firmament:lore": "Some Lore Requirement"
|
||||
}
|
||||
{
|
||||
"firmament:display_name": "SkyBlock Menu (Click)"
|
||||
},
|
||||
{
|
||||
"firmament:display_name": "SkyBlock",
|
||||
"firmament:lore": "Some Lore Requirement"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
This `firmament:any` test if the display name is either "SkyBlock Menu (Click)" or "SkyBlock" (aka any of the child predicates match).
|
||||
This `firmament:any` test if the display name is either "SkyBlock Menu (Click)" or "SkyBlock" (aka any of the child
|
||||
predicates match).
|
||||
|
||||
Similarly, there is `firmament:all`, which requires all of its children to match.
|
||||
|
||||
@@ -197,27 +201,28 @@ Directly specifying a raw string value expects the string to be *exactly* equal,
|
||||
|
||||
#### Complex
|
||||
|
||||
A complex string matcher allows you to specify whether the string will get its color codes removed or not before matching
|
||||
|
||||
A complex string matcher allows you to specify whether the string will get its color codes removed or not before
|
||||
matching
|
||||
|
||||
```json5
|
||||
"firmament:display_name": {
|
||||
"color": "strip",
|
||||
"color": "preserve",
|
||||
// When omitting the color property alltogether, you will fall back to "strip"
|
||||
"color": "strip",
|
||||
"color": "preserve",
|
||||
// When omitting the color property alltogether, you will fall back to "strip"
|
||||
}
|
||||
```
|
||||
|
||||
In that same object you can then also specify how the string will be matched using another property. You can only ever
|
||||
specify one of these other matchers and one color preserving property.
|
||||
|
||||
```json5
|
||||
"firmament:display_name": {
|
||||
"color": "strip",
|
||||
// You can use a "regex" property to use a java.util.Pattern regex. It will try to match the entire string.
|
||||
"regex": "So[me] Regex",
|
||||
// You can use an "equals" property to test if the entire string is equal to some value.
|
||||
// Equals is faster than regex, but also more limited.
|
||||
"equals": "Some Text"
|
||||
"color": "strip",
|
||||
// You can use a "regex" property to use a java.util.Pattern regex. It will try to match the entire string.
|
||||
"regex": "So[me] Regex",
|
||||
// You can use an "equals" property to test if the entire string is equal to some value.
|
||||
// Equals is faster than regex, but also more limited.
|
||||
"equals": "Some Text"
|
||||
}
|
||||
```
|
||||
|
||||
@@ -228,9 +233,10 @@ This matches a number against either a range or a specific number.
|
||||
#### Direct number
|
||||
|
||||
You can directly specify a number using that value directly:
|
||||
|
||||
```json5
|
||||
"firmament:pet": {
|
||||
"level": 100
|
||||
"level": 100
|
||||
}
|
||||
```
|
||||
|
||||
@@ -240,10 +246,9 @@ This is best for whole numbers, since decimal numbers can be really close togeth
|
||||
|
||||
For ranges you can instead use an interval. This uses the standard mathematical notation for those as a string:
|
||||
|
||||
|
||||
```json5
|
||||
"firmament:pet": {
|
||||
"level": "(50,100]"
|
||||
"level": "(50,100]"
|
||||
}
|
||||
```
|
||||
|
||||
@@ -266,7 +271,7 @@ compare your number:
|
||||
|
||||
```json5
|
||||
"firmament:pet": {
|
||||
"level": "<50"
|
||||
"level": "<50"
|
||||
}
|
||||
```
|
||||
|
||||
@@ -283,8 +288,8 @@ The `string` type matches like a regular [string matcher](#string-matcher):
|
||||
|
||||
```json
|
||||
"string": {
|
||||
"color": "strip",
|
||||
"regex": "^aaa bbb$"
|
||||
"color": "strip",
|
||||
"regex": "^aaa bbb$"
|
||||
}
|
||||
```
|
||||
|
||||
@@ -298,24 +303,24 @@ Or as a range:
|
||||
|
||||
```json
|
||||
"long": {
|
||||
"min": 0,
|
||||
"max": 1000
|
||||
"min": 0,
|
||||
"max": 1000
|
||||
}
|
||||
```
|
||||
|
||||
Min and max are both optional, but you need to specify at least one. By default `min` is inclusive and `max` is exclusive.
|
||||
Min and max are both optional, but you need to specify at least one. By default `min` is inclusive and `max` is
|
||||
exclusive.
|
||||
You can override that like so:
|
||||
|
||||
```json
|
||||
"short": {
|
||||
"min": 0,
|
||||
"max": 1000,
|
||||
"minExclusive": true,
|
||||
"maxExclusive": false
|
||||
"min": 0,
|
||||
"max": 1000,
|
||||
"minExclusive": true,
|
||||
"maxExclusive": false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
> [!WARNING]
|
||||
> This syntax for numbers is *just* for **NBT values**. This is also why specifying the type of the number is necessary.
|
||||
> For other number matchers, use [the number matchers](#number-matchers)
|
||||
@@ -328,16 +333,16 @@ To retexture a piece of armor place a json file at `assets/firmskyblock/override
|
||||
|
||||
```json
|
||||
{
|
||||
"item_ids": [
|
||||
"TARANTULA_BOOTS",
|
||||
"TARANTULA_LEGGINGS",
|
||||
// ETC
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"identifier": "firmskyblock:tarantula"
|
||||
}
|
||||
]
|
||||
"item_ids": [
|
||||
"TARANTULA_BOOTS",
|
||||
"TARANTULA_LEGGINGS"
|
||||
// ETC
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"identifier": "firmskyblock:tarantula"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
@@ -355,8 +360,8 @@ If you want to apply armor tint to the texture you will usually want two layers.
|
||||
|
||||
```json
|
||||
{
|
||||
"identifier": "firmskyblock:angler",
|
||||
"tint": true
|
||||
"identifier": "firmskyblock:angler",
|
||||
"tint": true
|
||||
}
|
||||
```
|
||||
|
||||
@@ -366,8 +371,8 @@ The second layer will have no tint applied, but will have a suffix:
|
||||
|
||||
```json
|
||||
{
|
||||
"identifier": "firmskyblock:angler",
|
||||
"suffix": "_overlay"
|
||||
"identifier": "firmskyblock:angler",
|
||||
"suffix": "_overlay"
|
||||
}
|
||||
```
|
||||
|
||||
@@ -388,33 +393,57 @@ Firmament predicates will work. You will also just directly specify new layers i
|
||||
|
||||
```json
|
||||
{
|
||||
"item_ids": [
|
||||
"TARANTULA_BOOTS",
|
||||
"TARANTULA_LEGGINGS",
|
||||
// ETC
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"identifier": "firmskyblock:tarantula"
|
||||
}
|
||||
],
|
||||
"overrides": [
|
||||
{
|
||||
"layers": [
|
||||
{
|
||||
"identifier": "firmskyblock:tarantula_maxed"
|
||||
}
|
||||
],
|
||||
"predicate": {
|
||||
"firmament:lore": {
|
||||
"regex": "Piece Bonus: +285.*"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
"item_ids": [
|
||||
"TARANTULA_BOOTS",
|
||||
"TARANTULA_LEGGINGS"
|
||||
// ETC
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"identifier": "firmskyblock:tarantula"
|
||||
}
|
||||
],
|
||||
"overrides": [
|
||||
{
|
||||
"layers": [
|
||||
{
|
||||
"identifier": "firmskyblock:tarantula_maxed"
|
||||
}
|
||||
],
|
||||
"predicate": {
|
||||
"firmament:lore": {
|
||||
"regex": "Piece Bonus: +285.*"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## UI Text Color Replacement
|
||||
|
||||
This allows you to replace the color of text in your inventory. This includes inventory UIs like chests and anvils, but
|
||||
not screens from other mods. You can also target specific texts via a [string matcher](#string-matcher).
|
||||
|
||||
```json
|
||||
// This file is at assets/firmskyblock/overrides/text_colors.json
|
||||
{
|
||||
"defaultColor": -10496,
|
||||
"overrides": [
|
||||
{
|
||||
"predicate": "Crafting",
|
||||
"override": -16711936
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
| Field | Required | Description |
|
||||
|-----------------------|----------|----------------------------------------------------------------------------------------------------|
|
||||
| `defaultColor` | true | The default color to use in case no override matches |
|
||||
| `overrides` | false | Allows you to replace colors for specific strings. Is an array. |
|
||||
| `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. |
|
||||
|
||||
## Global Item Texture Replacement
|
||||
|
||||
@@ -428,20 +457,20 @@ per override.
|
||||
|
||||
```json5
|
||||
{
|
||||
"screen": "testrp:chocolate_factory",
|
||||
"model": "testrp:time_tower",
|
||||
"predicate": {
|
||||
"firmament:display_name": {
|
||||
"regex": "Time Tower.*"
|
||||
}
|
||||
}
|
||||
"screen": "testrp:chocolate_factory",
|
||||
"model": "testrp:time_tower",
|
||||
"predicate": {
|
||||
"firmament:display_name": {
|
||||
"regex": "Time Tower.*"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
There are three parts to the override.
|
||||
|
||||
The `model` is an *item id* that the item will be replaced with. This means the
|
||||
model will be loaded from `assets/<namespace>/models/item/<id>.json`. Make sure to use your own namespace to
|
||||
model will be loaded from `assets/<namespace>/models/item/<id>.json`. Make sure to use your own namespace to
|
||||
avoid collisions with other texture packs that might use the same id for a gui.
|
||||
|
||||
The `predicate` is just a normal [predicate](#predicates). This one does not support the vanilla predicates. You can
|
||||
@@ -458,7 +487,7 @@ to avoid collisions with other texture packs that might use the same id for a sc
|
||||
|
||||
```json
|
||||
{
|
||||
"title": "Chocolate Factory"
|
||||
"title": "Chocolate Factory"
|
||||
}
|
||||
```
|
||||
|
||||
@@ -477,30 +506,30 @@ which block models are replaced under which conditions:
|
||||
|
||||
```json
|
||||
{
|
||||
"modes": [
|
||||
"mining_3"
|
||||
],
|
||||
"area": [
|
||||
{
|
||||
"min": [
|
||||
-31,
|
||||
200,
|
||||
-117
|
||||
],
|
||||
"max": [
|
||||
12,
|
||||
223,
|
||||
-95
|
||||
]
|
||||
}
|
||||
],
|
||||
"replacements": {
|
||||
"minecraft:blue_wool": "firmskyblock:mithril_deep",
|
||||
"minecraft:light_blue_wool": {
|
||||
"block": "firmskyblock:mithril_deep",
|
||||
"sound": "minecraft:block.wet_sponge.hit"
|
||||
}
|
||||
}
|
||||
"modes": [
|
||||
"mining_3"
|
||||
],
|
||||
"area": [
|
||||
{
|
||||
"min": [
|
||||
-31,
|
||||
200,
|
||||
-117
|
||||
],
|
||||
"max": [
|
||||
12,
|
||||
223,
|
||||
-95
|
||||
]
|
||||
}
|
||||
],
|
||||
"replacements": {
|
||||
"minecraft:blue_wool": "firmskyblock:mithril_deep",
|
||||
"minecraft:light_blue_wool": {
|
||||
"block": "firmskyblock:mithril_deep",
|
||||
"sound": "minecraft:block.wet_sponge.hit"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
package moe.nea.firmament.mixins;
|
||||
|
||||
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
|
||||
import moe.nea.firmament.features.texturepack.CustomTextColors;
|
||||
import net.minecraft.client.font.TextRenderer;
|
||||
import net.minecraft.client.gui.DrawContext;
|
||||
import net.minecraft.client.gui.screen.ingame.AnvilScreen;
|
||||
import net.minecraft.client.gui.screen.ingame.BeaconScreen;
|
||||
import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen;
|
||||
import net.minecraft.client.gui.screen.ingame.HandledScreen;
|
||||
import net.minecraft.client.gui.screen.ingame.InventoryScreen;
|
||||
import net.minecraft.client.gui.screen.ingame.MerchantScreen;
|
||||
import net.minecraft.text.Text;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
|
||||
@Mixin({HandledScreen.class, InventoryScreen.class, CreativeInventoryScreen.class, MerchantScreen.class,
|
||||
AnvilScreen.class, BeaconScreen.class})
|
||||
public class ReplaceTextColorInHandledScreen {
|
||||
|
||||
@WrapOperation(
|
||||
method = "drawForeground",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lnet/minecraft/client/gui/DrawContext;drawText(Lnet/minecraft/client/font/TextRenderer;Lnet/minecraft/text/Text;IIIZ)I"),
|
||||
expect = 0)
|
||||
private int replaceTextColorWithVariableShadow(DrawContext instance, TextRenderer textRenderer, Text text, int x, int y, int color, boolean shadow, Operation<Integer> original) {
|
||||
return original.call(instance, textRenderer, text, x, y, CustomTextColors.INSTANCE.mapTextColor(text, color), shadow);
|
||||
}
|
||||
|
||||
@WrapOperation(
|
||||
method = "drawForeground",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lnet/minecraft/client/gui/DrawContext;drawTextWithShadow(Lnet/minecraft/client/font/TextRenderer;Lnet/minecraft/text/Text;III)I"),
|
||||
expect = 0)
|
||||
private int replaceTextColorWithShadow(DrawContext instance, TextRenderer textRenderer, Text text, int x, int y, int color, Operation<Integer> original) {
|
||||
return original.call(instance, textRenderer, text, x, y, CustomTextColors.INSTANCE.mapTextColor(text, color));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -35,6 +35,7 @@ object CustomSkyBlockTextures : FirmamentFeature {
|
||||
val enableArmorOverrides by toggle("armor-overrides") { true }
|
||||
val enableBlockOverrides by toggle("block-overrides") { true }
|
||||
val enableLegacyCIT by toggle("legacy-cit") { true }
|
||||
val allowRecoloringUiText by toggle("recolor-text") { true }
|
||||
}
|
||||
|
||||
override val config: ManagedConfig
|
||||
|
||||
66
src/main/kotlin/features/texturepack/CustomTextColors.kt
Normal file
66
src/main/kotlin/features/texturepack/CustomTextColors.kt
Normal file
@@ -0,0 +1,66 @@
|
||||
package moe.nea.firmament.features.texturepack
|
||||
|
||||
import java.util.Optional
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlin.jvm.optionals.getOrNull
|
||||
import net.minecraft.resource.ResourceManager
|
||||
import net.minecraft.resource.SinglePreparationResourceReloader
|
||||
import net.minecraft.text.Text
|
||||
import net.minecraft.util.Identifier
|
||||
import net.minecraft.util.profiler.Profiler
|
||||
import moe.nea.firmament.Firmament
|
||||
import moe.nea.firmament.annotations.Subscribe
|
||||
import moe.nea.firmament.events.FinalizeResourceManagerEvent
|
||||
import moe.nea.firmament.util.collections.WeakCache
|
||||
|
||||
object CustomTextColors : SinglePreparationResourceReloader<CustomTextColors.TextOverrides?>() {
|
||||
@Serializable
|
||||
data class TextOverrides(
|
||||
val defaultColor: Int,
|
||||
val overrides: List<TextOverride> = listOf()
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class TextOverride(
|
||||
val predicate: StringMatcher,
|
||||
val override: Int,
|
||||
)
|
||||
|
||||
@Subscribe
|
||||
fun registerTextColorReloader(event: FinalizeResourceManagerEvent) {
|
||||
event.resourceManager.registerReloader(this)
|
||||
}
|
||||
|
||||
val cache = WeakCache.memoize<Text, Optional<Int>>("CustomTextColor") { text ->
|
||||
val override = textOverrides ?: return@memoize Optional.empty()
|
||||
Optional.of(override.overrides.find { it.predicate.matches(text) }?.override ?: override.defaultColor)
|
||||
}
|
||||
|
||||
fun mapTextColor(text: Text, oldColor: Int): Int {
|
||||
if (textOverrides == null) return oldColor
|
||||
return cache(text).getOrNull() ?: oldColor
|
||||
}
|
||||
|
||||
override fun prepare(
|
||||
manager: ResourceManager,
|
||||
profiler: Profiler
|
||||
): TextOverrides? {
|
||||
val resource = manager.getResource(Identifier.of("firmskyblock", "overrides/text_colors.json")).getOrNull()
|
||||
?: return null
|
||||
return Firmament.tryDecodeJsonFromStream<TextOverrides>(resource.inputStream)
|
||||
.getOrElse {
|
||||
Firmament.logger.error("Could not parse text_colors.json", it)
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
var textOverrides: TextOverrides? = null
|
||||
|
||||
override fun apply(
|
||||
prepared: TextOverrides?,
|
||||
manager: ResourceManager,
|
||||
profiler: Profiler
|
||||
) {
|
||||
textOverrides = prepared
|
||||
}
|
||||
}
|
||||
@@ -191,6 +191,7 @@
|
||||
"firmament.config.custom-skyblock-textures.cache-duration": "Model Cache Duration",
|
||||
"firmament.config.custom-skyblock-textures.model-overrides": "Enable model overrides/predicates",
|
||||
"firmament.config.custom-skyblock-textures.legacy-cit": "Enable legacy CIT Resewn compat",
|
||||
"firmament.config.custom-skyblock-textures.recolor-text": "Allow packs to recolor text",
|
||||
"firmament.config.custom-skyblock-textures.armor-overrides": "Enable Armor re-texturing",
|
||||
"firmament.config.custom-skyblock-textures.block-overrides": "Enable Block re-modelling",
|
||||
"firmament.config.custom-skyblock-textures.enabled": "Enable Custom Item Textures",
|
||||
|
||||
Reference in New Issue
Block a user