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
|
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
|
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,
|
`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.
|
as an example.
|
||||||
|
|
||||||
## (Placed) Skulls by texture id
|
## (Placed) Skulls by texture id
|
||||||
@@ -36,14 +37,17 @@ head model.
|
|||||||
"textures": {
|
"textures": {
|
||||||
"layer0": "firmskyblock:item/regular_texture"
|
"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)
|
"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
|
## Predicates
|
||||||
|
|
||||||
Firmament adds the ability for more complex [item model predicates](https://minecraft.wiki/w/Tutorials/Models#Item_predicates).
|
Firmament adds the ability for more
|
||||||
Those predicates work on any model, including models for vanilla items, but they don't mix very well with vanilla model overrides.
|
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
|
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.
|
firmament parser will result in an ignored predicate.
|
||||||
|
|
||||||
@@ -155,7 +159,6 @@ further filter by level and some other pet info.
|
|||||||
|
|
||||||
Every part of this matcher is optional.
|
Every part of this matcher is optional.
|
||||||
|
|
||||||
|
|
||||||
#### Logic Operators
|
#### Logic Operators
|
||||||
|
|
||||||
Logic operators allow to combine other firmament predicates into one. This is done by building boolean operators:
|
Logic operators allow to combine other firmament predicates into one. This is done by building boolean operators:
|
||||||
@@ -172,7 +175,8 @@ Logic operators allow to combine other firmament predicates into one. This is do
|
|||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
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.
|
Similarly, there is `firmament:all`, which requires all of its children to match.
|
||||||
|
|
||||||
@@ -197,8 +201,8 @@ Directly specifying a raw string value expects the string to be *exactly* equal,
|
|||||||
|
|
||||||
#### Complex
|
#### 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
|
```json5
|
||||||
"firmament:display_name": {
|
"firmament:display_name": {
|
||||||
@@ -207,6 +211,7 @@ A complex string matcher allows you to specify whether the string will get its c
|
|||||||
// When omitting the color property alltogether, you will fall back to "strip"
|
// 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
|
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.
|
specify one of these other matchers and one color preserving property.
|
||||||
|
|
||||||
@@ -228,6 +233,7 @@ This matches a number against either a range or a specific number.
|
|||||||
#### Direct number
|
#### Direct number
|
||||||
|
|
||||||
You can directly specify a number using that value directly:
|
You can directly specify a number using that value directly:
|
||||||
|
|
||||||
```json5
|
```json5
|
||||||
"firmament:pet": {
|
"firmament:pet": {
|
||||||
"level": 100
|
"level": 100
|
||||||
@@ -240,7 +246,6 @@ 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:
|
For ranges you can instead use an interval. This uses the standard mathematical notation for those as a string:
|
||||||
|
|
||||||
|
|
||||||
```json5
|
```json5
|
||||||
"firmament:pet": {
|
"firmament:pet": {
|
||||||
"level": "(50,100]"
|
"level": "(50,100]"
|
||||||
@@ -303,7 +308,8 @@ Or as a range:
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
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:
|
You can override that like so:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
@@ -315,7 +321,6 @@ You can override that like so:
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
> [!WARNING]
|
> [!WARNING]
|
||||||
> This syntax for numbers is *just* for **NBT values**. This is also why specifying the type of the number is necessary.
|
> 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)
|
> For other number matchers, use [the number matchers](#number-matchers)
|
||||||
@@ -330,7 +335,7 @@ To retexture a piece of armor place a json file at `assets/firmskyblock/override
|
|||||||
{
|
{
|
||||||
"item_ids": [
|
"item_ids": [
|
||||||
"TARANTULA_BOOTS",
|
"TARANTULA_BOOTS",
|
||||||
"TARANTULA_LEGGINGS",
|
"TARANTULA_LEGGINGS"
|
||||||
// ETC
|
// ETC
|
||||||
],
|
],
|
||||||
"layers": [
|
"layers": [
|
||||||
@@ -390,7 +395,7 @@ Firmament predicates will work. You will also just directly specify new layers i
|
|||||||
{
|
{
|
||||||
"item_ids": [
|
"item_ids": [
|
||||||
"TARANTULA_BOOTS",
|
"TARANTULA_BOOTS",
|
||||||
"TARANTULA_LEGGINGS",
|
"TARANTULA_LEGGINGS"
|
||||||
// ETC
|
// ETC
|
||||||
],
|
],
|
||||||
"layers": [
|
"layers": [
|
||||||
@@ -415,6 +420,30 @@ Firmament predicates will work. You will also just directly specify new layers i
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## 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
|
## Global Item Texture Replacement
|
||||||
|
|
||||||
|
|||||||
@@ -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 enableArmorOverrides by toggle("armor-overrides") { true }
|
||||||
val enableBlockOverrides by toggle("block-overrides") { true }
|
val enableBlockOverrides by toggle("block-overrides") { true }
|
||||||
val enableLegacyCIT by toggle("legacy-cit") { true }
|
val enableLegacyCIT by toggle("legacy-cit") { true }
|
||||||
|
val allowRecoloringUiText by toggle("recolor-text") { true }
|
||||||
}
|
}
|
||||||
|
|
||||||
override val config: ManagedConfig
|
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.cache-duration": "Model Cache Duration",
|
||||||
"firmament.config.custom-skyblock-textures.model-overrides": "Enable model overrides/predicates",
|
"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.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.armor-overrides": "Enable Armor re-texturing",
|
||||||
"firmament.config.custom-skyblock-textures.block-overrides": "Enable Block re-modelling",
|
"firmament.config.custom-skyblock-textures.block-overrides": "Enable Block re-modelling",
|
||||||
"firmament.config.custom-skyblock-textures.enabled": "Enable Custom Item Textures",
|
"firmament.config.custom-skyblock-textures.enabled": "Enable Custom Item Textures",
|
||||||
|
|||||||
Reference in New Issue
Block a user