diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 5620c78aa..91d83a17e 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -3,6 +3,7 @@ plugins { } repositories { + mavenLocal() maven("https://maven.fabricmc.net/") maven("https://maven.architectury.dev/") maven("https://maven.neoforged.net/releases/") @@ -13,7 +14,7 @@ repositories { dependencies { implementation("architectury-plugin:architectury-plugin.gradle.plugin:3.4-SNAPSHOT") - implementation("dev.architectury:architectury-loom:1.11-SNAPSHOT") + implementation("dev.architectury:architectury-loom:1.14-SNAPSHOT") implementation("com.gradleup.shadow:shadow-gradle-plugin:9.2.2") // Required to get Version Catalogs to show in buildSrc diff --git a/buildSrc/settings.gradle.kts b/buildSrc/settings.gradle.kts index 2dcd345a6..01c614210 100644 --- a/buildSrc/settings.gradle.kts +++ b/buildSrc/settings.gradle.kts @@ -1,5 +1,6 @@ pluginManagement { repositories { + mavenLocal() maven("https://maven.fabricmc.net/") maven("https://maven.architectury.dev/") maven("https://maven.neoforged.net/releases/") diff --git a/buildSrc/src/main/kotlin/io/wispforest/helpers/NeoForgeDataFilePublisher.kt b/buildSrc/src/main/kotlin/io/wispforest/helpers/NeoForgeDataFilePublisher.kt index 994116218..e7cf4cdd5 100644 --- a/buildSrc/src/main/kotlin/io/wispforest/helpers/NeoForgeDataFilePublisher.kt +++ b/buildSrc/src/main/kotlin/io/wispforest/helpers/NeoForgeDataFilePublisher.kt @@ -174,10 +174,10 @@ class PublishCallback { */ abstract class CopyDataFile : DefaultTask() { @get:InputFiles - abstract val inputFiles: ListProperty + abstract val inputFiles: ListProperty @get:OutputFiles - abstract val outputFiles: ListProperty + abstract val outputFiles: ListProperty @TaskAction @Throws(IOException::class) diff --git a/buildSrc/src/main/kotlin/io/wispforest/helpers/Utils.kt b/buildSrc/src/main/kotlin/io/wispforest/helpers/Utils.kt deleted file mode 100644 index f18596485..000000000 --- a/buildSrc/src/main/kotlin/io/wispforest/helpers/Utils.kt +++ /dev/null @@ -1,274 +0,0 @@ -package io.wispforest.helpers - -import kotlinx.serialization.json.Json -import kotlinx.serialization.json.JsonObject -import kotlinx.serialization.json.JsonPrimitive -import net.fabricmc.loom.configuration.ide.RunConfigSettings -import org.gradle.api.Action -import org.gradle.api.NamedDomainObjectContainer -import org.gradle.api.NamedDomainObjectProvider -import org.gradle.api.Project -import org.gradle.api.artifacts.Configuration -import org.gradle.api.artifacts.component.ModuleComponentIdentifier -import org.gradle.api.artifacts.dsl.RepositoryHandler -import org.gradle.api.tasks.SourceSetContainer -import org.gradle.kotlin.dsl.get -import org.gradle.kotlin.dsl.named -import java.net.URI - -object Utils { - private val Project.sourceSets: SourceSetContainer get() = - this.extensions.getByName("sourceSets") as SourceSetContainer - - private val NamedDomainObjectContainer.compileClasspath: NamedDomainObjectProvider get() = - named("compileClasspath") - - fun getSetupRunsAction(project: Project): Action> { - return Action { - val currentPlatform: String = ((project.properties["loom.platform"] as String?) ?: "common") - val rootProject = project.rootProject; - - val enabledMixinDebuggingPlatforms = (rootProject.property("enabled_mixin_debugging_platforms") as String).split(",") - val enabledRenderDocPlatforms = (rootProject.property("enabled_renderdoc_debugging_platforms") as String).split(","); - val enabledTestmodPlatforms = (rootProject.property("enabled_testmod_platforms") as String).split(","); - - val renderDocPath = System.getenv("renderDocPath"); - - val addMixinDebugginRuns = enabledMixinDebuggingPlatforms.contains(currentPlatform) - val addTestModRuns = enabledTestmodPlatforms.contains(currentPlatform) - - fun setupTestMod(settings: RunConfigSettings) { - project.afterEvaluate { - settings.source(project.sourceSets["testmod"]) - } - - if (currentPlatform != "neoforge") return - - settings.mods { - create("${rootProject.property("test_mod_id")}") { sourceSet(project.sourceSets["testmod"]) } - create("${rootProject.property("mod_id")}") { sourceSet(project.sourceSets["main"]) } - } - } - - if (addTestModRuns) { - create("testmodClient") { - client() - ideConfigGenerated(true) - name("Testmod Client") - setupTestMod(this) - } - create("testmodServer") { - server() - ideConfigGenerated(true) - name("Testmod Server") - setupTestMod(this) - } - } - - if (addMixinDebugginRuns) { - fun addMixinAsJavaAgent(settings: RunConfigSettings) { - // TODO: OUTSOURCE TO METHOD! - try { - project.afterEvaluate { - val mixin = this.configurations.compileClasspath.get() - .allDependencies - .asIterable() - .firstOrNull { it.name == "sponge-mixin" } - - if (mixin != null) { - val file = this.configurations.compileClasspath.get().incoming.artifactView { - componentFilter { id -> - if (id is ModuleComponentIdentifier) { - return@componentFilter id.moduleIdentifier.group == mixin.group - && id.moduleIdentifier.name == mixin.name - && id.version == mixin.version - } - - return@componentFilter false - } - }.files.first() - - settings.vmArg("-javaagent:\"${file.path}\"") - println("[Info]: Mixin Hotswap Run should be working") - } else { - println("[Warning]: Unable to locate file path for Mixin Jar, HotSwap Run will not work!!!") - } - } - } catch (e: Exception) { - println("[Error]: MixinHotswap Run had a issue!") - e.printStackTrace() - } - } - - create("clientMixinDebug") { - client() - ideConfigGenerated(true) - name("Minecraft Client - (Mixin Debug)") - vmArg("-Dfabric.dli.config=${project.file(".gradle/loom-cache/launch.cfg")}") - vmArg("-Dfabric.dli.env=client") - vmArg("-Dfabric.dli.main=net.fabricmc.loader.impl.launch.knot.KnotClient") - - addMixinAsJavaAgent(this); - - vmArg("-Dlog4j.configurationFile=${project.file(".gradle/loom-cache/log4j.xml")}") - vmArg("-Dfabric.log.disableAnsi=false") - vmArg("-Dmixin.debug.export=true") - } - - if (addTestModRuns) { - create("testmodClientMixinDebug") { - client() - ideConfigGenerated(true) - name("Testmod Client - (Mixin Debug)") - vmArg("-Dfabric.dli.config=${project.file(".gradle/loom-cache/launch.cfg")}") - vmArg("-Dfabric.dli.env=client") - vmArg("-Dfabric.dli.main=net.fabricmc.loader.impl.launch.knot.KnotClient") - - addMixinAsJavaAgent(this); - - vmArg("-Dlog4j.configurationFile=${project.file(".gradle/loom-cache/log4j.xml")}") - vmArg("-Dfabric.log.disableAnsi=false") - vmArg("-Dmixin.debug.export=true") - - setupTestMod(this) - } - } - } else { - println("Mixin Debugging for $currentPlatform is disabled just a FYI, adjust the gradle.properties 'enabled_mixin_debugging_platforms' field to contain such if you want the runs!") - } - - if (enabledRenderDocPlatforms.contains(currentPlatform)) { - if (renderDocPath != null) { - create("owoClientRenderDoc") { - client() - ideConfigGenerated(true) - name("Minecraft Client - (RenderDoc)") - source(project.sourceSets["main"]) - vmArg("-Dowo.renderdocPath=$renderDocPath") - } - if (addTestModRuns) { - create("testmodOwoClientRenderDoc") { - client() - ideConfigGenerated(true) - name("Testmod Client - (RenderDoc)") - source(project.sourceSets["testmod"]) - vmArg("-Dowo.renderdocPath=$renderDocPath") - - setupTestMod(this) - } - } - } else { - println("Unable to create Render Doc runs due to the renderDocPath variable is not found! Please add such and regenerate runs to get access if desired!") - } - } else { - println("Render Doc Debugging for $currentPlatform is disabled just a FYI, adjust the gradle.properties 'enabled_mixin_debugging_platforms' field to contain such if you want the runs!") - } - } - } - - //-- Fabric FMJ Entry Utils - const val removeLineTarget = "#REMOVE_LINE#" - const val baseIndentation = " " - - fun indentation (level: Int): String { - return baseIndentation.repeat(level); - } - - const val separator = ",\n" - - fun buildListEntry (project: Project, keys: List): String { - val rootProject = project.rootProject; - var entries = ""; - - keys.forEachIndexed { i: Int, key: String -> - if (key.isBlank()) return@forEachIndexed - - val contactKey = key.lowercase().replace(" ", "_"); - val hasContact = rootProject.hasProperty(contactKey) - - if (hasContact) { - if (i == 0) entries += "$removeLineTarget\"$separator" - - entries += - """{ - "name": "$key", - "contact": { - "homepage": "${rootProject.property(contactKey)}" - } -}""".prependIndent(indentation(2)) - } else { - if (i != 0) entries += "\""; - - entries += "$key\""; - } - entries += if (i < keys.size - 1) separator else "\n"; - } - - return entries + "${indentation(2)}\"$removeLineTarget"; - } - - fun buildMapEntry(project: Project, vararg keys: String): String { - val rootProject = project.rootProject; - var fullEntry = "$removeLineTarget\": \"\"$separator"; - - keys.forEachIndexed { i, key -> - fullEntry += run { - val propertyValue = rootProject.property("mod_$key") as String - "${indentation(2)}${(if (propertyValue.isNotBlank()) "\"$key\": \"$propertyValue\"" else "")}" - } - fullEntry += if (i < keys.size - 1) separator else "\n"; - } - - fullEntry += "${indentation(2)}\"$removeLineTarget" - - return fullEntry; - } - - fun currentPlatform(project: Project): String { - return ((project.properties["loom.platform"] as String?) ?: "common"); - } - - fun modId(project: Project): String { - return project.property("mod_id") as String - } - - /** - * The given function is designed to pull maven credentials from environment variables with the - * given key pattern of `${id}_maven_credentials` and accepting two types of JSON data format: - * - * - Parent: Allows for deferring credentials to another set of credentials. Code: `"parent_credentials":""` - * - Base: Declaring the `url`, `user`, and `password` in standard JSON format allows for individual projects - * to declare credentials. Code: `"url":"","user":"","password":""` - */ - fun setupMavenRepo(project: Project, repoHandler: RepositoryHandler) { - setupMavenRepo(modId(project), repoHandler) - } - - fun setupMavenRepo(id: String, repoHandler: RepositoryHandler) { - val mavenCredentials = System.getenv()["${id}_maven_credentials"] ?: return - val json = Json.decodeFromString("{${mavenCredentials}}") - - fun getContent(obj: JsonObject, key: String): String? { - val element = obj[key] ?: return null - return (element as? JsonPrimitive ?: throw IllegalStateException("'$id' maven credentials entry has the incorrect type! '$key' is not a JsonPrimitive: $element")).content - } - - fun getRequired(obj: JsonObject, key: String): String { - return getContent(obj, key) ?: throw IllegalStateException("'${id}' maven credentials was missing '${key}' as its required!") - } - - val parent = getContent(json, "parent_credentials") - - // Attempt to use parent project credentials instead of trying to use unique credentials for the project - if (parent != null) return setupMavenRepo(parent, repoHandler) - - repoHandler.maven { - url = URI.create(getRequired(json, "url")) - - credentials { - username = getRequired(json, "user") - password = getRequired(json, "password") - } - } - } -} \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/multiloader-base.gradle.kts b/buildSrc/src/main/kotlin/multiloader-base.gradle.kts index e05caef9c..dbf1969d0 100644 --- a/buildSrc/src/main/kotlin/multiloader-base.gradle.kts +++ b/buildSrc/src/main/kotlin/multiloader-base.gradle.kts @@ -7,7 +7,7 @@ import io.wispforest.helpers.RunConfigurationUtils.createExtraRunConfigs import io.wispforest.helpers.UtilsJava plugins { - id("dev.architectury.loom") + id("dev.architectury.loom-no-remap") id("maven-publish") id("base") id("java") @@ -81,6 +81,8 @@ loom { } repositories { + mavenLocal() // Local maven for custom owo-lib build + // Platform Mavens maven("https://maven.parchmentmc.org") maven("https://maven.fabricmc.net/") @@ -121,16 +123,6 @@ repositories { dependencies { minecraft("com.mojang:minecraft:${libs.versions.minecraft.asProvider().get()}") - if (name == "common-mojmap") { - mappings(loom.officialMojangMappings()) - } else { - mappings ( - loom.layered { - this.officialMojangMappings() - this.parchment("org.parchmentmc.data:parchment-${libs.versions.minecraft.asProvider().get()}:${libs.versions.parchment.get()}@zip") - } - ) - } if (projectPlatform != "common" && enabledTestmodPlatforms.contains(projectPlatform)) { "testmodImplementation"(sourceSets.main.get().output) @@ -139,7 +131,7 @@ dependencies { // General Libs var owolibDependency = if (projectPlatform == "neoforge") libs.owolib.neo else libs.owolib.fabric - modImplementation(owolibDependency) { + implementation(owolibDependency) { if (projectPlatform == "common") exclude("net.fabricmc.fabric-api") } annotationProcessor(owolibDependency) { @@ -153,7 +145,7 @@ dependencies { //-- // Item Viewer Libs - project.setupItemViewerDependencies(modCompileOnly = this::modCompileOnly, modLocalRuntime = this::modLocalRuntime) + project.setupItemViewerDependencies(modCompileOnly = this::compileOnly, modLocalRuntime = this::runtimeOnly) } tasks.processResources { diff --git a/buildSrc/src/main/kotlin/multiloader-mojmap.gradle.kts b/buildSrc/src/main/kotlin/multiloader-mojmap.gradle.kts index efe4b59e3..db7c68f24 100644 --- a/buildSrc/src/main/kotlin/multiloader-mojmap.gradle.kts +++ b/buildSrc/src/main/kotlin/multiloader-mojmap.gradle.kts @@ -38,8 +38,6 @@ fun setupTask(targetTask: AbstractRemapJarTask, taskName: String, archiveClassif targetTask.sourceNamespace = "named" targetTask.targetNamespace = "named" - //targetTask.remapperIsolation = true - targetTask.mustRunAfter( mutableListOf( tasks.namedOrNull("generateMetadataFileForMavenCommonPublication"), diff --git a/buildSrc/src/main/kotlin/multiloader-platform.gradle.kts b/buildSrc/src/main/kotlin/multiloader-platform.gradle.kts index af72acb31..e0c5bcdea 100644 --- a/buildSrc/src/main/kotlin/multiloader-platform.gradle.kts +++ b/buildSrc/src/main/kotlin/multiloader-platform.gradle.kts @@ -1,26 +1,27 @@ import io.wispforest.helpers.Extensions.currentPlatform import io.wispforest.helpers.Extensions.modId -import net.fabricmc.loom.task.service.MixinRefmapService - plugins { id("multiloader-base") id("com.gradleup.shadow") } val common by configurations.creating +val commonRuntime by configurations.creating val shadowCommon by configurations.creating configurations { common + commonRuntime shadowCommon // Don't use shadow from the shadow plugin since it *excludes* files. "compileClasspath" { extendsFrom(common) } - "runtimeClasspath" { extendsFrom(common) } + "runtimeClasspath" { extendsFrom(commonRuntime) } } // Setup platforms Shadow Configs dependencies { - "common"(project(":common", "namedElements")) { this.isTransitive = false } - "shadowCommon"(project(":common", "namedElements")) { this.isTransitive = false } + "common"(project(":common", "apiElements")) { this.isTransitive = false } + "commonRuntime"(project(":common", "runtimeElements")) { this.isTransitive = false } + "shadowCommon"(project(":common", "apiElements")) { this.isTransitive = false } } //-- Data Generation Setup Section @@ -95,18 +96,14 @@ tasks.shadowJar { // } } -// Remap the shadow jar to the proper platform mapping -tasks.remapJar { - inputFile.set(tasks.shadowJar.get().archiveFile) - dependsOn(tasks.shadowJar) +// No remapping needed for unobfuscated Minecraft 26.1 +tasks.shadowJar { archiveClassifier.set("") - if (currentPlatform == "fabric") injectAccessWidener = true - - var commonProject = project(":common"); - - var commonRemapJarTask = commonProject.tasks.remapJar.get(); +} - this.mixinRefmapServiceOptions.addAll(MixinRefmapService.createOptions(commonRemapJarTask)) +tasks.jar { + dependsOn(tasks.shadowJar) + enabled = false } // Add Common files to Source diff --git a/buildSrc/src/main/kotlin/multiloader-publishing.gradle.kts b/buildSrc/src/main/kotlin/multiloader-publishing.gradle.kts index 060e7787f..e4ada0135 100644 --- a/buildSrc/src/main/kotlin/multiloader-publishing.gradle.kts +++ b/buildSrc/src/main/kotlin/multiloader-publishing.gradle.kts @@ -23,31 +23,6 @@ publishing { } } - if (project.name == "common") { - create("mavenMojmap") { - val name = project.name - - version = "${rootProject.property("mod_version")}+${libs.versions.minecraft.asProvider().get()}-mojmap" - artifactId = "${modid}-${name}" - - afterEvaluate { - this@create.from(components["java"]) - - this@create.setArtifacts(emptyList()) - - val mojmapJarTask = project.tasks.named("mojmapJar"); - artifact(mojmapJarTask) { - builtBy(mojmapJarTask) - classifier = "" - } - val mojmapSourcesJarTask = project.tasks.named("mojmapSourcesJar"); - artifact(mojmapSourcesJarTask) { - builtBy(mojmapSourcesJarTask) - classifier = "sources" - } - } - } - } } MavenSetupUtils.setupMavenRepo(rootProject, repositories) diff --git a/common/build.gradle.kts b/common/build.gradle.kts index 3bad0de22..025a27cf9 100644 --- a/common/build.gradle.kts +++ b/common/build.gradle.kts @@ -2,10 +2,22 @@ import io.wispforest.helpers.Extensions.fabricModule import io.wispforest.helpers.Extensions.modrinth plugins { - id("multiloader-mojmap") + id("multiloader-base") id("multiloader-publishing") } +val enabledViewers = (rootProject.property("enabled_item_viewers") as String).split(",").filter { it.isNotBlank() } + +sourceSets { + main { + java { + if ("emi" !in enabledViewers) exclude("**/compat/emi/**") + if ("rei" !in enabledViewers) exclude("**/compat/rei/**") + if ("jei" !in enabledViewers) exclude("**/compat/jei/**") + } + } +} + dependencies { // Core Libs compileOnly(libs.mixin.extras.common) @@ -13,8 +25,8 @@ dependencies { // -- // General Libs - fabricModule(this::modCompileOnlyApi, "fabric-api-base") + fabricModule(this::compileOnlyApi, "fabric-api-base") // -- - modrinth(this::modCompileOnly, "sodium" to "${libs.versions.sodium.get()}-fabric") + modrinth(this::compileOnly, "sodium" to "${libs.versions.sodium.get()}-fabric") } diff --git a/common/src/main/java/io/wispforest/accessories/Accessories.java b/common/src/main/java/io/wispforest/accessories/Accessories.java index 725b7af6e..d207de57a 100644 --- a/common/src/main/java/io/wispforest/accessories/Accessories.java +++ b/common/src/main/java/io/wispforest/accessories/Accessories.java @@ -2,9 +2,11 @@ import com.google.common.reflect.Reflection; import com.mojang.logging.LogUtils; -import io.wispforest.accessories.api.core.Accessory; +import io.wispforest.accessories.api.action.ActionResponse; +import io.wispforest.accessories.api.action.ActionResponseBuffer; import io.wispforest.accessories.api.data.AccessoriesTags; -import io.wispforest.accessories.api.events.AllowEntityModificationCallback; +import io.wispforest.accessories.api.events.v2.AllowEntityModificationCallback; +import io.wispforest.accessories.api.tooltip.ComponentBuilder; import io.wispforest.accessories.commands.AccessoriesCommands; import io.wispforest.accessories.compat.config.AccessoriesConfig; import io.wispforest.accessories.criteria.AccessoryChangedCriterion; @@ -21,22 +23,21 @@ import net.fabricmc.fabric.api.util.TriState; import net.minecraft.commands.Commands; import net.minecraft.network.chat.Component; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.MinecraftServer; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.resources.Identifier; import net.minecraft.server.level.ServerPlayer; +import net.minecraft.server.players.NameAndId; import net.minecraft.util.ProblemReporter; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.OwnableEntity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.projectile.ProjectileUtil; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.GameRules; import net.minecraft.world.phys.EntityHitResult; import org.jetbrains.annotations.Nullable; import org.joml.Vector2i; import org.slf4j.Logger; -import java.util.function.BiConsumer; import java.util.function.Consumer; import java.util.function.Function; @@ -44,10 +45,10 @@ public class Accessories { public static final Logger LOGGER = LogUtils.getLogger(); - public static final ResourceLocation SLOT_LOADER_LOCATION = Accessories.of("slot_loader"); - public static final ResourceLocation ENTITY_SLOT_LOADER_LOCATION = Accessories.of("entity_slot_loader"); - public static final ResourceLocation SLOT_GROUP_LOADER_LOCATION = Accessories.of("slot_group_loader"); - public static final ResourceLocation DATA_RELOAD_HOOK = Accessories.of("data_reload_hook"); + public static final Identifier SLOT_LOADER_LOCATION = Accessories.of("slot_loader"); + public static final Identifier ENTITY_SLOT_LOADER_LOCATION = Accessories.of("entity_slot_loader"); + public static final Identifier SLOT_GROUP_LOADER_LOCATION = Accessories.of("slot_group_loader"); + public static final Identifier DATA_RELOAD_HOOK = Accessories.of("data_reload_hook"); public static final boolean DEBUG; @@ -64,26 +65,30 @@ public class Accessories { public static final String MODID = "accessories"; - public static ResourceLocation of(String path){ - return ResourceLocation.fromNamespaceAndPath(MODID, path); + public static Identifier of(String path){ + return Identifier.fromNamespaceAndPath(MODID, path); } - public static ResourceLocation parseLocationOrDefault(String s){ - var location = ResourceLocation.tryParse(s); + public static Identifier parseLocationOrDefault(String s){ + var location = Identifier.tryParse(s); if (location == null) location = Accessories.of(s); return location; } - public static String translationKey(String path){ - return MODID + "." + path; + public static String translationKey(String ...path){ + return MODID + "." + String.join(".", path); } - public static Component translation(String path) { + public static MutableComponent translation(String ...path) { return Component.translatable(translationKey(path)); } + public static ComponentBuilder translationWithArgs(String ...path) { + return (args) -> Component.translatable(translationKey(path), args); + } + //-- private static final AccessoriesConfig CONFIG = AccessoriesConfig.createAndLoad(serializationBuilder -> { @@ -121,9 +126,11 @@ public static void openAccessoriesMenu(Player player, AccessoriesMenuVariant var public static void openAccessoriesMenu(Player player, AccessoriesMenuVariant variant, @Nullable LivingEntity targetEntity, @Nullable ItemStack carriedStack) { if(targetEntity != null && !player.equals(targetEntity)) { - var result = AllowEntityModificationCallback.EVENT.invoker().allowModifications(targetEntity, player, null); + var buffer = new ActionResponseBuffer(false); - if(!result.orElse(false) && !player.hasPermissions(Commands.LEVEL_ADMINS)) return; + AllowEntityModificationCallback.EVENT.invoker().allowModifications(targetEntity, player, null, buffer); + + if(!buffer.canPerformAction().isValid(false) && !(player instanceof ServerPlayer sp && Commands.LEVEL_ADMINS.check(sp.permissions()))) return; } AccessoriesInternals.INSTANCE.openAccessoriesMenu(player, variant, targetEntity, carriedStack); @@ -139,16 +146,23 @@ public static void init() { AccessoriesCommands.init(); - AllowEntityModificationCallback.EVENT.register((target, player, reference) -> { + AllowEntityModificationCallback.EVENT.register((target, player, reference, buffer) -> { var type = target.getType(); - if(type.is(AccessoriesTags.MODIFIABLE_ENTITY_BLACKLIST)) return TriState.FALSE; + if(type.builtInRegistryHolder().is(AccessoriesTags.MODIFIABLE_ENTITY_BLACKLIST)) { + buffer.respondWith(ActionResponse.of(false, Component.literal("Given entity can not be manged by you!"))); + return; + } var isOwnersPet = (target instanceof OwnableEntity ownableEntity && ownableEntity.getOwner() != null && ownableEntity.getOwner().equals(player)); - if(isOwnersPet || type.is(AccessoriesTags.MODIFIABLE_ENTITY_WHITELIST)) return TriState.TRUE; - - return TriState.DEFAULT; + if(isOwnersPet || type.builtInRegistryHolder().is(AccessoriesTags.MODIFIABLE_ENTITY_WHITELIST)) { + buffer.respondWith(ActionResponse.of(true, + isOwnersPet + ? Component.literal("Your pet can be managed by you.") + : Component.literal("Given entity can be manged by you.")) + ); + } }); ArmorSlotTypes.INSTANCE.init(); diff --git a/common/src/main/java/io/wispforest/accessories/AccessoriesClientInternals.java b/common/src/main/java/io/wispforest/accessories/AccessoriesClientInternals.java index 53c515fc2..c7179fbd5 100644 --- a/common/src/main/java/io/wispforest/accessories/AccessoriesClientInternals.java +++ b/common/src/main/java/io/wispforest/accessories/AccessoriesClientInternals.java @@ -1,9 +1,13 @@ package io.wispforest.accessories; -import io.wispforest.accessories.pond.TooltipFlagExtension; -import io.wispforest.accessories.utils.ServiceLoaderUtils; +import io.wispforest.accessories.api.tooltip.*; +import io.wispforest.accessories.pond.TooltipFlagExtended; +import net.minecraft.network.chat.FormattedText; +import net.minecraft.network.chat.Style; import net.minecraft.world.item.TooltipFlag; -import org.jetbrains.annotations.Nullable; + +import java.util.Collection; +import java.util.stream.Stream; public abstract class AccessoriesClientInternals { @@ -25,7 +29,62 @@ public static void setInstance(AccessoriesClientInternals instance) { hasInstanceBeenSet = true; } - public TooltipFlag createTooltipFlag(TooltipFlag flag) { - return TooltipFlagExtension.createFlag(flag, Integer.MAX_VALUE); + public TooltipComponentBuilder createTooltipBuilder() { + return new TooltipComponentBuilder() { + @Override + public TooltipComponentBuilder add(TooltipComponentHolder holder) { + return this; + } + + @Override + public TooltipComponentBuilder divider() { + return this; + } + + @Override + public TooltipComponentBuilder divider(int height) { + return this; + } + + @Override + public TooltipComponentBuilder add(FormattedText text) { + return this; + } + + @Override + public TooltipComponentBuilder add(TooltipComponentBuilder builder) { + return this; + } + + @Override + public TooltipComponentBuilder addAll(Collection text) { + return this; + } + + @Override + public TooltipComponentBuilder addAll(TextPrefixer prefixer, FormattedTextBuilder builder) { + return this; + } + + public boolean isEmpty() { + return true; + } + }; + } + + public TextWrapper createWrapper(int maxWidth, Style overrideStyle) { + return TextWrapper.NONE; + } + + public TooltipFlag createTooltipFlag() { + return TooltipFlagExtended.create(false); + } + + public int createBitFlag() { + return createBitFlag(true, true, true); + } + + public int createBitFlag(boolean hasShift, boolean hasControl, boolean hasAlt) { + return Integer.MAX_VALUE; } } diff --git a/common/src/main/java/io/wispforest/accessories/AccessoriesInternals.java b/common/src/main/java/io/wispforest/accessories/AccessoriesInternals.java index 387e2ca88..8297f7673 100644 --- a/common/src/main/java/io/wispforest/accessories/AccessoriesInternals.java +++ b/common/src/main/java/io/wispforest/accessories/AccessoriesInternals.java @@ -11,7 +11,7 @@ import net.minecraft.core.Holder; import net.minecraft.network.chat.Component; import net.minecraft.resources.RegistryOps; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.packs.PackType; @@ -29,7 +29,7 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.TooltipFlag; import net.minecraft.world.item.component.TooltipDisplay; -import net.minecraft.world.level.GameRules; +import net.minecraft.world.level.gamerules.GameRules; import org.apache.commons.lang3.function.TriFunction; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; @@ -100,9 +100,9 @@ public void setInternalEquipmentSlotType(EquipmentSlot.Type type) { public abstract void giveItemToPlayer(ServerPlayer player, ItemStack stack); - public abstract boolean isValidOnConditions(JsonObject object, String dataType, ResourceLocation key, SimplePreparableReloadListener listener, @Nullable RegistryOps.RegistryInfoLookup registryInfo); + public abstract boolean isValidOnConditions(JsonObject object, String dataType, Identifier key, SimplePreparableReloadListener listener, @Nullable RegistryOps.RegistryInfoLookup registryInfo); - public abstract MenuType registerMenuType(ResourceLocation location, Endec endec, TriFunction func); + public abstract MenuType registerMenuType(Identifier location, Endec endec, TriFunction func); public abstract void openAccessoriesMenu(Player player, AccessoriesMenuVariant variant, @Nullable LivingEntity targetEntity, @Nullable ItemStack carriedStack); @@ -113,4 +113,6 @@ public void setInternalEquipmentSlotType(EquipmentSlot.Type type) { //-- public abstract String getTagTranslation(TagKey tagKey); + + public abstract String geEntryTranslation(Holder entry); } diff --git a/common/src/main/java/io/wispforest/accessories/api/AccessoriesAPI.java b/common/src/main/java/io/wispforest/accessories/api/AccessoriesAPI.java index 1eb1db70c..7916e7e0c 100644 --- a/common/src/main/java/io/wispforest/accessories/api/AccessoriesAPI.java +++ b/common/src/main/java/io/wispforest/accessories/api/AccessoriesAPI.java @@ -9,9 +9,10 @@ import io.wispforest.accessories.api.slot.SlotPredicateRegistry; import io.wispforest.accessories.api.slot.SlotReference; import io.wispforest.accessories.api.slot.SlotType; +import io.wispforest.accessories.api.slot.validator.SlotValidatorRegistry; import io.wispforest.accessories.impl.AccessoryAttributeLogic; import net.minecraft.core.Holder; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.world.Container; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.ai.attributes.Attribute; @@ -93,12 +94,12 @@ public static boolean isDefaultAccessory(Accessory accessory) { */ @Deprecated(forRemoval = true) public static boolean isValidAccessory(ItemStack stack, Level level){ - return SlotPredicateRegistry.isValidAccessory(stack, level); + return SlotValidatorRegistry.isValidAccessory(stack, level); } @Deprecated(forRemoval = true) public static boolean isValidAccessory(ItemStack stack, Level level, @Nullable LivingEntity entity){ - return SlotPredicateRegistry.isValidAccessory(stack, level, entity); + return SlotValidatorRegistry.isValidAccessory(stack, level, entity); } //-- @@ -133,7 +134,7 @@ public static AccessoryAttributeBuilder getAttributeModifiers(ItemStack stack, @ } @Deprecated(forRemoval = true) - public static void addAttribute(ItemStack stack, String slotName, Holder attribute, ResourceLocation location, double amount, AttributeModifier.Operation operation, boolean isStackable) { + public static void addAttribute(ItemStack stack, String slotName, Holder attribute, Identifier location, double amount, AttributeModifier.Operation operation, boolean isStackable) { AccessoryAttributeUtils.addAttribute(stack, slotName, attribute, location, amount, operation, isStackable); } @@ -143,7 +144,7 @@ public static void addAttribute(ItemStack stack, String slotName, Holder getValidSlotTypes(LivingEntity entity, ItemStack stack){ - return SlotPredicateRegistry.getValidSlotTypes(entity, stack); + return SlotValidatorRegistry.getValidSlotTypes(entity, stack); } @Deprecated(forRemoval = true) public static Collection getStackSlotTypes(Level level, ItemStack stack){ - return SlotPredicateRegistry.getStackSlotTypes(level, null, stack); + return SlotValidatorRegistry.getStackSlotTypes(level, null, stack); } @Deprecated(forRemoval = true) public static Collection getStackSlotTypes(LivingEntity entity, ItemStack stack) { - return SlotPredicateRegistry.getStackSlotTypes(entity.level(), entity, stack); + return SlotValidatorRegistry.getStackSlotTypes(entity.level(), entity, stack); } @Deprecated(forRemoval = true) public static Collection getStackSlotTypes(Level level, @Nullable LivingEntity entity, ItemStack stack) { - return SlotPredicateRegistry.getStackSlotTypes(level, entity, stack); + return SlotValidatorRegistry.getStackSlotTypes(level, entity, stack); } @Deprecated(forRemoval = true) @@ -233,22 +234,22 @@ public static void breakStack(SlotReference reference){ @Deprecated(forRemoval = true) @Nullable - public static SlotBasedPredicate getPredicate(ResourceLocation location) { + public static SlotBasedPredicate getPredicate(Identifier location) { return SlotPredicateRegistry.getPredicate(location); } @Deprecated(forRemoval = true) - public static void registerPredicate(ResourceLocation location, SlotBasedPredicate predicate) { + public static void registerPredicate(Identifier location, SlotBasedPredicate predicate) { SlotPredicateRegistry.register(location, predicate); } @Deprecated(forRemoval = true) - public static boolean getPredicateResults(Set predicateIds, Level level, SlotType slotType, int index, ItemStack stack){ - return SlotPredicateRegistry.getPredicateResults(predicateIds, level, null, slotType, index, stack); + public static boolean getPredicateResults(Set predicateIds, Level level, SlotType slotType, int index, ItemStack stack){ + return SlotValidatorRegistry.getPredicateResults(predicateIds, level, null, slotType, index, stack); } @Deprecated(forRemoval = true) - public static boolean getPredicateResults(Set predicateIds, Level level, @Nullable LivingEntity entity, SlotType slotType, int index, ItemStack stack){ - return SlotPredicateRegistry.getPredicateResults(predicateIds, level, entity, slotType, index, stack); + public static boolean getPredicateResults(Set predicateIds, Level level, @Nullable LivingEntity entity, SlotType slotType, int index, ItemStack stack){ + return SlotValidatorRegistry.getPredicateResults(predicateIds, level, entity, slotType, index, stack); } } \ No newline at end of file diff --git a/common/src/main/java/io/wispforest/accessories/api/AccessoriesCapability.java b/common/src/main/java/io/wispforest/accessories/api/AccessoriesCapability.java index ea9f94224..8c6ff2770 100644 --- a/common/src/main/java/io/wispforest/accessories/api/AccessoriesCapability.java +++ b/common/src/main/java/io/wispforest/accessories/api/AccessoriesCapability.java @@ -8,6 +8,7 @@ import io.wispforest.accessories.api.equip.EquipCheck; import io.wispforest.accessories.api.equip.EquipmentChecking; import io.wispforest.accessories.api.slot.*; +import io.wispforest.accessories.api.slot.validator.SlotValidatorRegistry; import io.wispforest.accessories.data.SlotTypeLoader; import io.wispforest.accessories.impl.core.AccessoriesHolderImpl; import io.wispforest.accessories.pond.AccessoriesAPIAccess; @@ -44,7 +45,7 @@ static Collection getUsedSlotsFor(Player player) { } static Collection getUsedSlotsFor(LivingEntity entity, Container container) { - var capability = entity.accessoriesCapability(); + var capability = ((io.wispforest.accessories.pond.AccessoriesAPIAccess) entity).accessoriesCapability(); return (capability != null) ? capability.getUsedSlotsFor(container) : Set.of(); } @@ -90,11 +91,11 @@ default Collection getUsedSlotsFor(Container container) { if (stack.isEmpty()) continue; - slots.addAll(SlotPredicateRegistry.getValidSlotTypes(entity, stack)); + slots.addAll(SlotValidatorRegistry.getValidSlotTypes(entity, stack)); } for (var ref : this.getAllEquipped()) { - slots.addAll(SlotPredicateRegistry.getValidSlotTypes(entity, ref.stack())); + slots.addAll(SlotValidatorRegistry.getValidSlotTypes(entity, ref.stack())); } slots.addAll(SlotTypeLoader.getUsedSlotsByRegistryItem(entity)); diff --git a/common/src/main/java/io/wispforest/accessories/api/AccessoriesContainer.java b/common/src/main/java/io/wispforest/accessories/api/AccessoriesContainer.java index c8590ce21..727d316dd 100644 --- a/common/src/main/java/io/wispforest/accessories/api/AccessoriesContainer.java +++ b/common/src/main/java/io/wispforest/accessories/api/AccessoriesContainer.java @@ -3,7 +3,7 @@ import io.wispforest.accessories.api.slot.SlotReference; import io.wispforest.accessories.api.slot.SlotType; import io.wispforest.accessories.impl.core.ExpandedContainer; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.world.Container; import net.minecraft.world.entity.ai.attributes.AttributeModifier; @@ -78,7 +78,7 @@ default void markChanged() { /// /// @return All slot modifiers applied to the given Container /// - Map getModifiers(); + Map getModifiers(); /// /// @return All cached modifiers sent within sync packet to the client @@ -108,13 +108,13 @@ default void markChanged() { /// Remove the specific attribute modifier from the map if found /// @param location The specific location /// - boolean hasModifier(ResourceLocation location); + boolean hasModifier(Identifier location); /// /// Remove the specific attribute modifier from the map if found /// @param location The specific location /// - void removeModifier(ResourceLocation location); + void removeModifier(Identifier location); /// /// Remove all modifiers from the given container diff --git a/common/src/main/java/io/wispforest/accessories/api/action/ActionResponse.java b/common/src/main/java/io/wispforest/accessories/api/action/ActionResponse.java new file mode 100644 index 000000000..f534409b0 --- /dev/null +++ b/common/src/main/java/io/wispforest/accessories/api/action/ActionResponse.java @@ -0,0 +1,59 @@ +package io.wispforest.accessories.api.action; + +import io.wispforest.accessories.api.tooltip.ListTooltipAdder; +import io.wispforest.accessories.utils.ComponentOps; +import net.minecraft.network.chat.Component; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.TooltipFlag; + +/// +/// Acts as a holder for a [ValidationState] and message used to tell if +/// an action can or can not be performed with a default value being letting +/// the caller decided the outcome. +/// +public interface ActionResponse extends ReasonProvider { + + static ActionResponse SUCCESS = of(true, Component.empty()); + + //-- + + static ActionResponse of(boolean canPerformAction, Component reason) { + return of(ValidationState.of(canPerformAction), reason); + } + + static ActionResponse of(ValidationState state, Component reason) { + return of(state, (callback, ctx, type) -> { + callback.add(ComponentOps.validateComponent(reason, "ActionResponse")); + }); + } + + static ActionResponse of(ValidationState state, ReasonProvider provider) { + return new ActionResponseBase(state) { + @Override + public void addInfo(ListTooltipAdder adder, Item.TooltipContext ctx, TooltipFlag type) { + provider.addInfo(adder, ctx, type); + } + }; + } + + //-- + + /// + /// @return The resultant of the response indicating either its [VALID][ValidationState#VALID], + /// [INVALID][ValidationState#INVALID], or [IRRELEVANT][ValidationState#IRRELEVANT] to the + /// outcome of the action check. + /// + ValidationState canPerformAction(); + + @Override + void addInfo(ListTooltipAdder adder, Item.TooltipContext ctx, TooltipFlag flag); + + //-- + + @Override + boolean equals(Object obj); + + @Override + int hashCode(); + +} diff --git a/common/src/main/java/io/wispforest/accessories/api/action/ActionResponseBase.java b/common/src/main/java/io/wispforest/accessories/api/action/ActionResponseBase.java new file mode 100644 index 000000000..a5852674b --- /dev/null +++ b/common/src/main/java/io/wispforest/accessories/api/action/ActionResponseBase.java @@ -0,0 +1,22 @@ +package io.wispforest.accessories.api.action; + +/// +/// Base version of [ActionResponse] that acts a starting point for +/// custom responses. +/// +public abstract class ActionResponseBase implements ActionResponse { + protected final ValidationState canPerformAction; + + protected ActionResponseBase(boolean canPerformAction) { + this(ValidationState.of(canPerformAction)); + } + + protected ActionResponseBase(ValidationState canPerformAction) { + this.canPerformAction = canPerformAction; + } + + @Override + public ValidationState canPerformAction() { + return canPerformAction; + } +} diff --git a/common/src/main/java/io/wispforest/accessories/api/action/ActionResponseBuffer.java b/common/src/main/java/io/wispforest/accessories/api/action/ActionResponseBuffer.java new file mode 100644 index 000000000..a57886908 --- /dev/null +++ b/common/src/main/java/io/wispforest/accessories/api/action/ActionResponseBuffer.java @@ -0,0 +1,115 @@ +package io.wispforest.accessories.api.action; + +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +/// +/// Acts as a buffer to hold all responses for a given Action check. +/// +/// If [#allowEarlyReturn] is found to be true, will attempt to return if any response is found to have a result +/// of [INVALID][ValidationState#INVALID] with the **requirement** being that outside callers must check [#shouldReturnEarly()] +/// to see if they need to break out of iteration loop. +/// +public class ActionResponseBuffer { + + @Nullable + private final ActionResponseBuffer parent; + private final List responses = new ArrayList<>(); + + private final boolean allowEarlyReturn; + + private boolean shouldReturnEarly = false; + + private ValidationState canPerformAction = ValidationState.IRRELEVANT; + + public ActionResponseBuffer(boolean allowEarlyReturn) { + this(null, allowEarlyReturn); + } + + private ActionResponseBuffer(ActionResponseBuffer parent, boolean allowEarlyReturn) { + this.parent = parent; + this.allowEarlyReturn = allowEarlyReturn; + } + + //-- + + public void respondWith(ActionResponse response) { + responses.add(response); + + var value = response.canPerformAction(); + + if (canPerformAction == value) return; + + if (value == ValidationState.INVALID) { + canPerformAction = ValidationState.INVALID; + + if (allowEarlyReturn) shouldReturnEarly = true; + } else if (value == ValidationState.VALID && canPerformAction == ValidationState.IRRELEVANT) { + canPerformAction = ValidationState.VALID; + } + } + + /// + /// @return If the given outer iteration loop should cancel early because of a result within the buffer + /// + public boolean shouldReturnEarly() { + return shouldReturnEarly; + } + + /// + /// @return The final resultant of the buffers contents, as checked within [#respondWith(ActionResponse)], + /// indicating either its [VALID][ValidationState#VALID], [INVALID][ValidationState#INVALID], + /// or [IRRELEVANT][ValidationState#IRRELEVANT] to the outcome of the action check. + /// + public ValidationState canPerformAction() { + return canPerformAction; + } + + /// + /// @return Whether the given buffer has any responses + /// + public boolean isEmpty() { + return responses.isEmpty(); + } + + /// + /// @return An immutable view of the responses within the buffer + /// + public List responses() { + return Collections.unmodifiableList(responses); + } + + /// + /// @return An immutable filtered view of the responses within the buffer partially based on the + /// buffers [#canPerformAction()] value + /// + public List responses(boolean filterValidStates) { + return responses(filterValidStates, canPerformAction.isValid()); + } + + /// + /// @return An immutable filtered view of the responses within the buffer. + /// + public List responses(boolean filterValidStates, boolean filterIrrelevantStates) { + if (responses.isEmpty()) return List.of(); + + var stream = responses.stream().filter(response -> { + var value = response.canPerformAction(); + + if (value == ValidationState.VALID && filterValidStates) return false; + if (value == ValidationState.IRRELEVANT && filterIrrelevantStates) return false; + + return true; + }); + + if(!(filterValidStates && filterIrrelevantStates)) { + stream = stream.sorted(Comparator.comparing(ActionResponse::canPerformAction)); + } + + return stream.toList(); + } +} diff --git a/common/src/main/java/io/wispforest/accessories/api/action/CurseBound.java b/common/src/main/java/io/wispforest/accessories/api/action/CurseBound.java new file mode 100644 index 000000000..5161df05f --- /dev/null +++ b/common/src/main/java/io/wispforest/accessories/api/action/CurseBound.java @@ -0,0 +1,46 @@ +package io.wispforest.accessories.api.action; + +import io.wispforest.accessories.api.tooltip.ListTooltipAdder; +import io.wispforest.accessories.api.tooltip.impl.ListTooltipEntry; +import net.minecraft.network.chat.Component; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.TooltipFlag; +import net.minecraft.world.item.enchantment.EnchantmentEffectComponents; +import net.minecraft.world.item.enchantment.EnchantmentHelper; + +public class CurseBound extends ActionResponseBase { + + protected CurseBound() { + super(false); + } + + public static boolean checkIfCursed(ItemStack stack, LivingEntity entity, ActionResponseBuffer buffer) { + if(EnchantmentHelper.has(stack, EnchantmentEffectComponents.PREVENT_ARMOR_CHANGE)) { + if (!(entity instanceof Player player) || !player.isCreative()) { + buffer.respondWith(new CurseBound()); + + return true; + } + } + + return false; + } + + @Override + public void addInfo(ListTooltipAdder adder, Item.TooltipContext ctx, TooltipFlag type) { + adder.add(Component.translatable("accessories.tooltip.validator.cursed")); + } + + @Override + public boolean equals(Object obj) { + return obj instanceof CurseBound; + } + + @Override + public int hashCode() { + return CurseBound.class.hashCode(); + } +} diff --git a/common/src/main/java/io/wispforest/accessories/api/action/HolderSetValidationResponse.java b/common/src/main/java/io/wispforest/accessories/api/action/HolderSetValidationResponse.java new file mode 100644 index 000000000..eca16f5c5 --- /dev/null +++ b/common/src/main/java/io/wispforest/accessories/api/action/HolderSetValidationResponse.java @@ -0,0 +1,101 @@ +package io.wispforest.accessories.api.action; + +import io.wispforest.accessories.Accessories; +import io.wispforest.accessories.AccessoriesInternals; +import io.wispforest.accessories.api.tooltip.ComponentBuilder; +import io.wispforest.accessories.api.tooltip.ListTooltipAdder; +import io.wispforest.accessories.utils.CollectionUtils; +import net.minecraft.core.Holder; +import net.minecraft.core.HolderSet; +import net.minecraft.core.Registry; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.ComponentUtils; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.tags.TagKey; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.TooltipFlag; +import org.jetbrains.annotations.Nullable; + +import java.util.Map; +import java.util.SequencedCollection; +import java.util.SequencedMap; + +public class HolderSetValidationResponse extends ActionResponseBase { + + private final HolderSet set; + private final Holder holder; + private final Registry registry; + private final SequencedMap, ComponentBuilder> tagFormatting; + + public HolderSetValidationResponse(Registry registry, TagKey tag, Holder holder) { + this(registry, registry.get(tag).map(holders -> (HolderSet) holders).orElse(HolderSet.empty()), holder); + } + + public HolderSetValidationResponse(SequencedCollection> holders, Holder holder) { + this(null, HolderSet.direct(holders.stream().toList()), holder); + } + + public HolderSetValidationResponse(@Nullable Registry registry, HolderSet set, Holder holder) { + super(ValidationState.ofOrIrrelevant(set.stream().anyMatch(entry -> holder.is(holder)))); + + if (holder.kind().equals(Holder.Kind.DIRECT)) { + throw new IllegalStateException("Unable to handle Holder '" + holder + "' as it was found to be Directly made instead of being a Reference which is required!"); + } + + this.set = set; + this.holder = holder; + this.registry = registry == null ? (Registry) BuiltInRegistries.REGISTRY.getValue(holder.unwrapKey().get().registry()) : registry; + + this.tagFormatting = set.stream() + .map(entry -> Map.entry(entry, getFormatting(entry, entry))) + .collect(CollectionUtils.linkedMapCollector()); + } + + private static ComponentBuilder getFormatting(Holder holder, Holder entry) { + return ValidationState.of(holder.is(entry)).asColorBuilder(); + } + + public Registry registry() { + return registry; + } + + public SequencedMap, ComponentBuilder> tagFormatting() { + return tagFormatting; + } + + public HolderSet getSet() { + return set; + } + + public Holder getEntry() { + return holder; + } + + @Override + public void addInfo(ListTooltipAdder adder, Item.TooltipContext ctx, TooltipFlag type) { + MutableComponent baseMsg; + + var infoType = this.canPerformAction().formatedName(false); + + var registryLangKey = registry.key().identifier().toLanguageKey(); + + if (type.isAdvanced() || ((io.wispforest.accessories.pond.TooltipFlagExtended) type).hasShiftDown()) { + var tags = ComponentUtils.formatList( + this.tagFormatting().entrySet(), + Accessories.translation("tooltip.validator.set.entry_separator"), + entry -> entry.getValue().withArgs(Component.translatable(AccessoriesInternals.INSTANCE.geEntryTranslation(entry.getKey()))) + ); + + // accessories.tooltip.validator.set.advanced.{valid | invalid} + baseMsg = Accessories.translationWithArgs("tooltip.validator.set.advanced", infoType) + .withArgs(Component.translatable(registryLangKey + ".plural"), tags); + } else { + // accessories.tooltip.validator.set.basic.{valid | invalid} + baseMsg = Accessories.translationWithArgs("tooltip.validator.set.simple", infoType) + .withArgs(Component.translatable(registryLangKey + ".singular")); + } + + adder.add(baseMsg); + } +} diff --git a/common/src/main/java/io/wispforest/accessories/api/action/ReasonProvider.java b/common/src/main/java/io/wispforest/accessories/api/action/ReasonProvider.java new file mode 100644 index 000000000..f83dfd662 --- /dev/null +++ b/common/src/main/java/io/wispforest/accessories/api/action/ReasonProvider.java @@ -0,0 +1,16 @@ +package io.wispforest.accessories.api.action; + +import io.wispforest.accessories.api.tooltip.ListTooltipAdder; +import io.wispforest.accessories.api.tooltip.impl.ListTooltipEntry; +import io.wispforest.accessories.api.tooltip.TooltipInfoProvider; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.TooltipFlag; + +/// +/// Base classed used by [ActionResponse] as a way to allow for more info +/// to be provided in a tooltip typically used to give meaning to an action +/// result. +/// +public interface ReasonProvider extends TooltipInfoProvider { + void addInfo(ListTooltipAdder adder, Item.TooltipContext ctx, TooltipFlag type); +} diff --git a/common/src/main/java/io/wispforest/accessories/api/action/SlotValidationResponse.java b/common/src/main/java/io/wispforest/accessories/api/action/SlotValidationResponse.java new file mode 100644 index 000000000..f84153112 --- /dev/null +++ b/common/src/main/java/io/wispforest/accessories/api/action/SlotValidationResponse.java @@ -0,0 +1,80 @@ +package io.wispforest.accessories.api.action; + +import io.wispforest.accessories.Accessories; +import io.wispforest.accessories.api.tooltip.ListTooltipAdder; +import io.wispforest.accessories.api.tooltip.impl.ListTooltipEntry; +import io.wispforest.accessories.api.data.AccessoriesBaseData; +import io.wispforest.accessories.api.slot.SlotType; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.ComponentUtils; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.TooltipFlag; + +import java.util.Objects; +import java.util.SequencedCollection; + +public class SlotValidationResponse extends ActionResponseBase { + + private final String slotName; + + private final SequencedCollection validSlots; + private final SequencedCollection invalidSlots; + + public SlotValidationResponse(String slotName, SequencedCollection validSlots, SequencedCollection invalidSlots) { + super(isValid(slotName, validSlots, invalidSlots)); + + this.slotName = slotName; + + this.validSlots = validSlots; + this.invalidSlots = invalidSlots; + } + + public static ValidationState isValid(String slotName, SequencedCollection validSlots, SequencedCollection invalidSlots) { + if (invalidSlots.contains(slotName)) { + return ValidationState.INVALID; + } else if (validSlots.contains(slotName) || validSlots.contains(AccessoriesBaseData.ANY_SLOT)) { + return ValidationState.VALID; + } else { + return ValidationState.IRRELEVANT; + } + } + + public String getSlotName() { + return slotName; + } + + public SequencedCollection getValidSlots() { + return validSlots; + } + + public SequencedCollection getInvalidSlots() { + return invalidSlots; + } + + @Override + public void addInfo(ListTooltipAdder adder, Item.TooltipContext ctx, TooltipFlag type) { + var state = this.canPerformAction(); + + SequencedCollection slots = switch (this.canPerformAction()) { + case INVALID -> getInvalidSlots(); + case VALID, IRRELEVANT -> getValidSlots(); + }; + + if (!slots.isEmpty()) { + var slotNames = ComponentUtils.formatList( + slots, + Accessories.translation("tooltip.validator.component.entry_separator"), + slotName -> { + return (Objects.equals(slotName, this.slotName) || Objects.equals(slotName, "any") ? state : ValidationState.IRRELEVANT) + .asColorBuilder() + .withArgs(Component.translatable(SlotType.toTranslationKey(slotName))); + } + ); + + adder.add(Accessories.translationWithArgs("tooltip.validator.component.advanced", this.canPerformAction().formatedName()).withArgs(slotNames)); + } else { + adder.add(Accessories.translation("tooltip.validator.component.simple", this.canPerformAction().formatedName())); + } + } + +} diff --git a/common/src/main/java/io/wispforest/accessories/api/action/TagValidationResponse.java b/common/src/main/java/io/wispforest/accessories/api/action/TagValidationResponse.java new file mode 100644 index 000000000..31cba19d0 --- /dev/null +++ b/common/src/main/java/io/wispforest/accessories/api/action/TagValidationResponse.java @@ -0,0 +1,133 @@ +package io.wispforest.accessories.api.action; + +import io.wispforest.accessories.Accessories; +import io.wispforest.accessories.AccessoriesInternals; +import io.wispforest.accessories.api.tooltip.ComponentBuilder; +import io.wispforest.accessories.api.tooltip.ListTooltipAdder; +import io.wispforest.accessories.utils.CollectionUtils; +import io.wispforest.accessories.utils.ComponentOps; +import net.minecraft.core.Holder; +import net.minecraft.core.Registry; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.tags.TagKey; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.TooltipFlag; + +import java.util.*; + +public class TagValidationResponse extends ActionResponseBase { + + public static final TagCheckOperation ANY_MATCH = new TagCheckOperation() { + @Override + public boolean isValid(Holder holder, SequencedCollection> tags) { + return tags.stream().anyMatch(holder::is); + } + + @Override + public ComponentBuilder tagFormatting(Holder holder, TagKey tag) { + return ValidationState.ofOrIrrelevant(holder.is(tag)).asColorBuilder(); + } + + @Override + public String name() { + return "any"; + } + }; + + public static final TagCheckOperation ALL_MATCH = new TagCheckOperation() { + @Override + public boolean isValid(Holder holder, SequencedCollection> tags) { + return tags.stream().allMatch(holder::is); + } + + @Override + public ComponentBuilder tagFormatting(Holder holder, TagKey tag) { + return ValidationState.of(holder.is(tag)).asColorBuilder(); + } + + @Override + public String name() { + return "all"; + } + }; + + private final List> tags; + private final Holder entry; + private final Registry registry; + private final TagCheckOperation operation; + + private final SequencedMap, ComponentBuilder> tagFormatting; + + public TagValidationResponse(Holder entry, SequencedCollection> tags, TagCheckOperation operation) { + super(operation.isValidChecked(entry, tags) ? ValidationState.VALID : ValidationState.IRRELEVANT); + + if (entry.kind().equals(Holder.Kind.DIRECT)) { + throw new IllegalStateException("Unable to handle Holder '" + entry + "' as it was found to be Directly made instead of being a Reference which is required!"); + } + + this.tags = List.copyOf(tags); + this.entry = entry; + this.registry = (Registry) BuiltInRegistries.REGISTRY.getValue(entry.unwrapKey().get().registry()); + this.operation = operation; + + this.tagFormatting = tags.stream() + .map(tagKey -> Map.entry(tagKey, operation.tagFormatting(entry, tagKey))) + .collect(CollectionUtils.linkedMapCollector()); + } + + public Registry registry() { + return registry; + } + + public List> getTags() { + return tags; + } + + public Holder getEntry() { + return entry; + } + + public TagCheckOperation operation() { + return operation; + } + + @Override + public void addInfo(ListTooltipAdder adder, Item.TooltipContext ctx, TooltipFlag type) { + MutableComponent baseMsg; + + var stateName = this.canPerformAction().formatedName(false); + + if (type.isAdvanced() || ((io.wispforest.accessories.pond.TooltipFlagExtended) type).hasShiftDown()) { + var tags = ComponentOps.fromEntriesDivided( + this.tagFormatting.sequencedEntrySet(), + "validator.tag", + entry -> entry.getValue() + .withArgs(Component.translatable(AccessoriesInternals.INSTANCE.getTagTranslation(entry.getKey()))) + ); + + // accessories.tooltip.validator.tag.advanced.{valid | invalid}.{any | all | [...custom_name]} + baseMsg = Accessories.translationWithArgs("tooltip.validator.tag.advanced", stateName, this.operation().name()) + .withArgs(tags); + } else { + // accessories.tooltip.validator.tag.basic.{valid | invalid} + baseMsg = Accessories.translation("tooltip.validator.tag.simple", stateName); + } + + adder.add(baseMsg); + } + + public interface TagCheckOperation { + + default boolean isValidChecked(Holder holder, SequencedCollection> tags) { + return holder.kind().equals(Holder.Kind.REFERENCE) && isValid(holder, tags); + } + + boolean isValid(Holder holder, SequencedCollection> tags); + + String name(); + + ComponentBuilder tagFormatting(Holder holder, TagKey tag); + } +} diff --git a/common/src/main/java/io/wispforest/accessories/api/action/ValidationState.java b/common/src/main/java/io/wispforest/accessories/api/action/ValidationState.java new file mode 100644 index 000000000..62ff3d888 --- /dev/null +++ b/common/src/main/java/io/wispforest/accessories/api/action/ValidationState.java @@ -0,0 +1,92 @@ +package io.wispforest.accessories.api.action; + +import io.wispforest.accessories.Accessories; +import io.wispforest.accessories.api.tooltip.ComponentBuilder; +import net.fabricmc.fabric.api.util.TriState; +import net.minecraft.network.chat.MutableComponent; +import org.jetbrains.annotations.Nullable; + +import java.awt.*; +import java.util.Locale; + +/// +/// An enum class used to indicate if a given response is valid, invalid, irrelevant. +/// +public enum ValidationState { + /// + /// Invalid means that something about the given input is unable to perform the given action. + /// + INVALID, + /// + /// Valid means that something about the given input is able to perform the given action. + /// + VALID, + /// + /// Irrelevant means that something about the given input was found to not indicate any invalid or valid reasons + /// to preform the action. Typically, means that the action must use other responses if any to determine if + /// the action is valid or invalid. + /// + IRRELEVANT; + + public String formatedName(boolean allowIrrelevant) { + return (!allowIrrelevant && this == IRRELEVANT) + ? INVALID.formatedName() + : formatedName(); + } + + public String formatedName() { + return this.name().toLowerCase(Locale.ROOT); + } + + public boolean isValid() { + return this == VALID; + } + + public boolean isValid(boolean defaultValue) { + return isValid() || (this == IRRELEVANT && defaultValue); + } + + public @Nullable Boolean unbox() { + return switch (this) { + case INVALID -> false; + case VALID -> true; + case IRRELEVANT -> null; + }; + } + + public TriState toTriState() { + return switch (this) { + case INVALID -> TriState.FALSE; + case VALID -> TriState.TRUE; + case IRRELEVANT -> TriState.DEFAULT; + }; + } + + public static ValidationState of(boolean isValid) { + return isValid ? VALID : INVALID; + } + + public static ValidationState ofOrIrrelevant(boolean isValid) { + return (isValid ? VALID : IRRELEVANT); + } + + public static ValidationState of(TriState state) { + return switch (state) { + case FALSE -> ValidationState.INVALID; + case TRUE -> ValidationState.VALID; + case DEFAULT -> ValidationState.IRRELEVANT; + }; + } + + public ComponentBuilder asColorBuilder() { + return Accessories.translationWithArgs("tooltip.slot", this.name().toLowerCase(Locale.ROOT)); + } + + public MutableComponent asEntryComponent() { + return switch (this) { + case VALID -> Accessories.translation("tooltip.equipment_reasoning.list_entry.valid"); + case INVALID -> Accessories.translation("tooltip.equipment_reasoning.list_entry.invalid"); + case IRRELEVANT -> Accessories.translation("tooltip.equipment_reasoning.list_entry.irrelevant"); + }; + } +} diff --git a/common/src/main/java/io/wispforest/accessories/api/attributes/AccessoryAttributeBuilder.java b/common/src/main/java/io/wispforest/accessories/api/attributes/AccessoryAttributeBuilder.java index 472be2051..3158eeb82 100644 --- a/common/src/main/java/io/wispforest/accessories/api/attributes/AccessoryAttributeBuilder.java +++ b/common/src/main/java/io/wispforest/accessories/api/attributes/AccessoryAttributeBuilder.java @@ -9,7 +9,7 @@ import io.wispforest.accessories.api.slot.SlotPath; import io.wispforest.accessories.api.slot.SlotReference; import net.minecraft.core.Holder; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.world.entity.ai.attributes.Attribute; import net.minecraft.world.entity.ai.attributes.AttributeModifier; import org.jetbrains.annotations.ApiStatus; @@ -30,7 +30,7 @@ public final class AccessoryAttributeBuilder { private static final Logger LOGGER = LogUtils.getLogger(); - private final Map, Map> exclusiveAttributes; + private final Map, Map> exclusiveAttributes; private final Multimap, AttributeModificationData> stackedAttributes; private final SlotPath slotPath; @@ -68,7 +68,7 @@ public AccessoryAttributeBuilder() { /** * Adds a given attribute modifier as an exclusive modifier meaning that only one instance should ever exist */ - public AccessoryAttributeBuilder addExclusive(Holder attribute, ResourceLocation location, double amount, AttributeModifier.Operation operation) { + public AccessoryAttributeBuilder addExclusive(Holder attribute, Identifier location, double amount, AttributeModifier.Operation operation) { return this.addExclusive(attribute, location, amount, operation, false); } @@ -76,14 +76,14 @@ public AccessoryAttributeBuilder addExclusive(Holder attribute, Resou * Adds a given attribute modifier as a stackable modifier meaning variants based on slot position is allowed. This is done by post process * step of appending slot information when adding to the living entity */ - public AccessoryAttributeBuilder addStackable(Holder attribute, ResourceLocation location, double amount, AttributeModifier.Operation operation) { + public AccessoryAttributeBuilder addStackable(Holder attribute, Identifier location, double amount, AttributeModifier.Operation operation) { return this.addStackable(attribute, location, amount, operation, false); } /** * Adds a given attribute modifier as an exclusive modifier meaning that only one instance should ever exist */ - public AccessoryAttributeBuilder addExclusive(Holder attribute, ResourceLocation location, double amount, AttributeModifier.Operation operation, boolean usedInSlotValidation) { + public AccessoryAttributeBuilder addExclusive(Holder attribute, Identifier location, double amount, AttributeModifier.Operation operation, boolean usedInSlotValidation) { return this.addExclusive(attribute, new AttributeModifier(location, amount, operation), usedInSlotValidation); } @@ -91,7 +91,7 @@ public AccessoryAttributeBuilder addExclusive(Holder attribute, Resou * Adds a given attribute modifier as a stackable modifier meaning variants based on slot position is allowed. This is done by post process * step of appending slot information when adding to the living entity */ - public AccessoryAttributeBuilder addStackable(Holder attribute, ResourceLocation location, double amount, AttributeModifier.Operation operation, boolean usedInSlotValidation) { + public AccessoryAttributeBuilder addStackable(Holder attribute, Identifier location, double amount, AttributeModifier.Operation operation, boolean usedInSlotValidation) { return this.addStackable(attribute, new AttributeModifier(location, amount, operation), usedInSlotValidation); } @@ -103,7 +103,7 @@ public AccessoryAttributeBuilder addStackable(Holder attribute, Attri return this.addStackable(attribute, modifier, false); } - private final Set previouslyWarnedLocations = new HashSet<>(); + private final Set previouslyWarnedLocations = new HashSet<>(); /** * Adds a given attribute modifier as an exclusive modifier meaning that only one instance should ever exist @@ -137,7 +137,7 @@ public AccessoryAttributeBuilder addStackable(Holder attribute, Attri //-- @Nullable - public AttributeModificationData getExclusive(Holder attribute, ResourceLocation location) { + public AttributeModificationData getExclusive(Holder attribute, Identifier location) { var innerMap = this.exclusiveAttributes.get(attribute); if(innerMap == null) return null; @@ -145,12 +145,12 @@ public AttributeModificationData getExclusive(Holder attribute, Resou return innerMap.get(location); } - public Collection getStacks(Holder attribute, ResourceLocation location) { + public Collection getStacks(Holder attribute, Identifier location) { return this.stackedAttributes.get(attribute).stream().filter(data -> data.modifier().id().equals(location)).toList(); } @Nullable - public AttributeModificationData removeExclusive(Holder attribute, ResourceLocation location) { + public AttributeModificationData removeExclusive(Holder attribute, Identifier location) { var innerMap = this.exclusiveAttributes.get(attribute); if(innerMap == null) return null; @@ -158,7 +158,7 @@ public AttributeModificationData removeExclusive(Holder attribute, Re return innerMap.remove(location); } - public Collection removeStacks(Holder attribute, ResourceLocation location) { + public Collection removeStacks(Holder attribute, Identifier location) { Set removedData = new HashSet<>(); for (var data : List.copyOf(this.stackedAttributes.get(attribute))) { @@ -226,7 +226,7 @@ public boolean isEmpty() { return this.exclusiveAttributes.isEmpty() && this.stackedAttributes.isEmpty(); } - public Map, Map> exclusiveAttributes() { + public Map, Map> exclusiveAttributes() { return ImmutableMap.copyOf(this.exclusiveAttributes); } diff --git a/common/src/main/java/io/wispforest/accessories/api/attributes/AccessoryAttributeUtils.java b/common/src/main/java/io/wispforest/accessories/api/attributes/AccessoryAttributeUtils.java index fa3b2c58d..df427aa9a 100644 --- a/common/src/main/java/io/wispforest/accessories/api/attributes/AccessoryAttributeUtils.java +++ b/common/src/main/java/io/wispforest/accessories/api/attributes/AccessoryAttributeUtils.java @@ -3,7 +3,7 @@ import io.wispforest.accessories.api.components.AccessoriesDataComponents; import io.wispforest.accessories.api.components.AccessoryItemAttributeModifiers; import net.minecraft.core.Holder; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.world.entity.ai.attributes.Attribute; import net.minecraft.world.entity.ai.attributes.AttributeModifier; import net.minecraft.world.item.ItemStack; @@ -17,7 +17,7 @@ /// public class AccessoryAttributeUtils { - public static void addAttribute(ItemStack stack, String slotName, Holder attribute, ResourceLocation location, double amount, AttributeModifier.Operation operation, boolean isStackable) { + public static void addAttribute(ItemStack stack, String slotName, Holder attribute, Identifier location, double amount, AttributeModifier.Operation operation, boolean isStackable) { stack.update( AccessoriesDataComponents.ATTRIBUTES, new AccessoryItemAttributeModifiers(List.of(), true), @@ -25,7 +25,7 @@ public static void addAttribute(ItemStack stack, String slotName, Holder attribute, ResourceLocation location) { + public static void removeAttribute(ItemStack stack, Holder attribute, Identifier location) { stack.update( AccessoriesDataComponents.ATTRIBUTES, new AccessoryItemAttributeModifiers(List.of(), true), diff --git a/common/src/main/java/io/wispforest/accessories/api/attributes/SlotAttribute.java b/common/src/main/java/io/wispforest/accessories/api/attributes/SlotAttribute.java index 1c9070614..e5d1659ee 100644 --- a/common/src/main/java/io/wispforest/accessories/api/attributes/SlotAttribute.java +++ b/common/src/main/java/io/wispforest/accessories/api/attributes/SlotAttribute.java @@ -3,7 +3,7 @@ import com.google.common.collect.Multimap; import io.wispforest.accessories.api.slot.SlotType; import net.minecraft.core.Holder; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.world.entity.ai.attributes.Attribute; import net.minecraft.world.entity.ai.attributes.AttributeModifier; import net.minecraft.world.item.ItemStack; @@ -57,15 +57,15 @@ public static Holder getAttributeHolder(String slotName){ //-- - public static void addSlotModifier(Multimap, AttributeModifier> map, SlotType slotType, ResourceLocation location, double amount, AttributeModifier.Operation operation) { + public static void addSlotModifier(Multimap, AttributeModifier> map, SlotType slotType, Identifier location, double amount, AttributeModifier.Operation operation) { addSlotModifier(map, slotType.name(), location, amount, operation); } - public static void addSlotModifier(Multimap, AttributeModifier> map, String slot, ResourceLocation location, double amount, AttributeModifier.Operation operation) { + public static void addSlotModifier(Multimap, AttributeModifier> map, String slot, Identifier location, double amount, AttributeModifier.Operation operation) { map.put(SlotAttribute.getAttributeHolder(slot), new AttributeModifier(location, amount, operation)); } - public static void addSlotAttribute(AccessoryAttributeBuilder builder, String targetSlot, ResourceLocation location, double amount, AttributeModifier.Operation operation, boolean isStackable) { + public static void addSlotAttribute(AccessoryAttributeBuilder builder, String targetSlot, Identifier location, double amount, AttributeModifier.Operation operation, boolean isStackable) { if(isStackable) { builder.addStackable(SlotAttribute.getAttributeHolder(targetSlot), location, amount, operation); } else { @@ -73,7 +73,7 @@ public static void addSlotAttribute(AccessoryAttributeBuilder builder, String ta } } - public static void addSlotAttribute(ItemStack stack, String targetSlot, String boundSlot, ResourceLocation location, double amount, AttributeModifier.Operation operation, boolean isStackable) { + public static void addSlotAttribute(ItemStack stack, String targetSlot, String boundSlot, Identifier location, double amount, AttributeModifier.Operation operation, boolean isStackable) { AccessoryAttributeUtils.addAttribute(stack, boundSlot, SlotAttribute.getAttributeHolder(targetSlot), location, amount, operation, isStackable); } } diff --git a/common/src/main/java/io/wispforest/accessories/api/client/AccessoriesRenderStateKeys.java b/common/src/main/java/io/wispforest/accessories/api/client/AccessoriesRenderStateKeys.java index 42c107d57..dcda50475 100644 --- a/common/src/main/java/io/wispforest/accessories/api/client/AccessoriesRenderStateKeys.java +++ b/common/src/main/java/io/wispforest/accessories/api/client/AccessoriesRenderStateKeys.java @@ -9,7 +9,7 @@ import net.minecraft.client.renderer.entity.state.EntityRenderState; import net.minecraft.client.renderer.entity.state.LivingEntityRenderState; import net.minecraft.client.renderer.item.ItemStackRenderState; -import net.minecraft.client.renderer.state.CameraRenderState; +import net.minecraft.client.renderer.state.level.CameraRenderState; import net.minecraft.util.context.ContextKey; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.HumanoidArm; @@ -45,7 +45,7 @@ public class AccessoriesRenderStateKeys { public static void setupStateForAccessories(EntityRenderState state, Entity entity, float partialTick, HumanoidArm arm) { - if (state instanceof LivingEntityRenderState livingState) livingState.setStateData(ARM, arm); + if (state instanceof LivingEntityRenderState livingState) ((io.wispforest.accessories.pond.AccessoriesRenderStateAPImpl) livingState).setStateData(ARM, arm); setupStateForAccessories(state, entity, partialTick); } @@ -53,12 +53,12 @@ public static void setupStateForAccessories(EntityRenderState state, Entity enti public static void setupStateForAccessories(EntityRenderState state, Entity entity, float partialTick) { if (!(state instanceof LivingEntityRenderState livingState) || !(entity instanceof LivingEntity livingEntity)) return; - livingState.setStateData(AccessoriesRenderStateKeys.ENTITY_UUID, livingEntity.getUUID()); - livingState.setStateData(AccessoriesRenderStateKeys.ENTITY_ID, livingEntity.getId()); + ((io.wispforest.accessories.pond.AccessoriesRenderStateAPImpl) livingState).setStateData(AccessoriesRenderStateKeys.ENTITY_UUID, livingEntity.getUUID()); + ((io.wispforest.accessories.pond.AccessoriesRenderStateAPImpl) livingState).setStateData(AccessoriesRenderStateKeys.ENTITY_ID, livingEntity.getId()); - livingState.setStateData(AccessoriesRenderStateKeys.PARTIAL_TICKS, partialTick); + ((io.wispforest.accessories.pond.AccessoriesRenderStateAPImpl) livingState).setStateData(AccessoriesRenderStateKeys.PARTIAL_TICKS, partialTick); - var capability = livingEntity.accessoriesCapability(); + var capability = ((io.wispforest.accessories.pond.AccessoriesAPIAccess) livingEntity).accessoriesCapability(); if (capability == null) return; @@ -72,7 +72,7 @@ public static void setupStateForAccessories(EntityRenderState state, Entity enti AccessoriesStorageLookup lookup = () -> map; - livingState.setStateData(AccessoriesRenderStateKeys.STORAGE_LOOKUP, lookup); + ((io.wispforest.accessories.pond.AccessoriesRenderStateAPImpl) livingState).setStateData(AccessoriesRenderStateKeys.STORAGE_LOOKUP, lookup); var renderStates = new LinkedHashMap(); @@ -104,6 +104,6 @@ public static void setupStateForAccessories(EntityRenderState state, Entity enti } } - livingState.setStateData(AccessoriesRenderStateKeys.ACCESSORY_RENDER_STATES, renderStates); + ((io.wispforest.accessories.pond.AccessoriesRenderStateAPImpl) livingState).setStateData(AccessoriesRenderStateKeys.ACCESSORY_RENDER_STATES, renderStates); } } diff --git a/common/src/main/java/io/wispforest/accessories/api/client/AccessoriesRendererRegistry.java b/common/src/main/java/io/wispforest/accessories/api/client/AccessoriesRendererRegistry.java index dc7890e56..da67337b8 100644 --- a/common/src/main/java/io/wispforest/accessories/api/client/AccessoriesRendererRegistry.java +++ b/common/src/main/java/io/wispforest/accessories/api/client/AccessoriesRendererRegistry.java @@ -11,7 +11,7 @@ import io.wispforest.accessories.api.components.AccessoriesDataComponents; import io.wispforest.accessories.api.core.AccessoryRegistry; import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; @@ -31,23 +31,23 @@ */ public class AccessoriesRendererRegistry { - public static final ResourceLocation NO_RENDERER_ID = Accessories.of("no_renderer"); + public static final Identifier NO_RENDERER_ID = Accessories.of("no_renderer"); private static final Logger LOGGER = LogUtils.getLogger(); - private static final Map ITEM_TO_RENDERER = new HashMap<>(); - private static final Map DATA_LOADED_ITEM_TO_RENDERER = new HashMap<>(); + private static final Map ITEM_TO_RENDERER = new HashMap<>(); + private static final Map DATA_LOADED_ITEM_TO_RENDERER = new HashMap<>(); - private static final Map> RENDERERS = new HashMap<>(); + private static final Map> RENDERERS = new HashMap<>(); - private static final BiMap CACHED_RENDERERS = HashBiMap.create(); + private static final BiMap CACHED_RENDERERS = HashBiMap.create(); /** - * Binds the given item to use the following renderer as registered though {@link AccessoriesRendererRegistry#registerRenderer(ResourceLocation, Supplier)} + * Binds the given item to use the following renderer as registered though {@link AccessoriesRendererRegistry#registerRenderer(Identifier, Supplier)} * @param item * @param rendererId */ - public static void bindItemToRenderer(Item item, ResourceLocation rendererId) { + public static void bindItemToRenderer(Item item, Identifier rendererId) { var entry = ITEM_TO_RENDERER.putIfAbsent(item, rendererId); if (entry != null) { @@ -55,7 +55,7 @@ public static void bindItemToRenderer(Item item, ResourceLocation rendererId) { } } - public static void bindItemToRenderer(Item item, ResourceLocation rendererId, Supplier renderer) { + public static void bindItemToRenderer(Item item, Identifier rendererId, Supplier renderer) { bindItemToRenderer(item, rendererId); registerRenderer(rendererId, renderer); @@ -78,7 +78,7 @@ public static void bindItemToArmorRenderer(Item item){ bindItemToRenderer(item, BuiltinAccessoryRenderers.ARMOR_RENDERER_ID); } - public static void registerRenderer(ResourceLocation location, Supplier renderer) { + public static void registerRenderer(Identifier location, Supplier renderer) { RENDERERS.put(location, renderer); } @@ -88,7 +88,7 @@ public static boolean hasRenderer(Item item) { return getBoundRenderer(item) != null; } - public static boolean hasRenderer(ResourceLocation rendererId) { + public static boolean hasRenderer(Identifier rendererId) { return RENDERERS.containsKey(rendererId); } @@ -145,19 +145,19 @@ public static AccessoryRenderer getRenderer(Item item){ } @Nullable - public static AccessoryRenderer getRenderer(ResourceLocation rendererId) { + public static AccessoryRenderer getRenderer(Identifier rendererId) { if (rendererId.equals(NO_RENDERER_ID)) return new BuiltinAccessoryRenderers.EmptyRenderer(); return CACHED_RENDERERS.get(rendererId); } @Nullable - public static ResourceLocation getRendererId(AccessoryRenderer renderer) { + public static Identifier getRendererId(AccessoryRenderer renderer) { return CACHED_RENDERERS.inverse().get(renderer); } @Nullable - public static ResourceLocation getBoundRenderer(Item item) { + public static Identifier getBoundRenderer(Item item) { if (DATA_LOADED_ITEM_TO_RENDERER.containsKey(item)) { return DATA_LOADED_ITEM_TO_RENDERER.get(item); } @@ -168,7 +168,7 @@ public static ResourceLocation getBoundRenderer(Item item) { //-- @ApiStatus.Internal - public static void setDataLoadedItemToRenderer(Map data) { + public static void setDataLoadedItemToRenderer(Map data) { DATA_LOADED_ITEM_TO_RENDERER.clear(); DATA_LOADED_ITEM_TO_RENDERER.putAll(data); } @@ -201,7 +201,7 @@ public static void onReload() { //-- @Deprecated(forRemoval = true) - public static ResourceLocation getRendererId(Item item) { + public static Identifier getRendererId(Item item) { return BuiltInRegistries.ITEM.getKey(item); } diff --git a/common/src/main/java/io/wispforest/accessories/api/client/DefaultedContextKey.java b/common/src/main/java/io/wispforest/accessories/api/client/DefaultedContextKey.java index fa84e190f..a6efe0d87 100644 --- a/common/src/main/java/io/wispforest/accessories/api/client/DefaultedContextKey.java +++ b/common/src/main/java/io/wispforest/accessories/api/client/DefaultedContextKey.java @@ -1,6 +1,6 @@ package io.wispforest.accessories.api.client; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.util.context.ContextKey; import java.util.function.Supplier; @@ -8,7 +8,7 @@ public class DefaultedContextKey extends ContextKey { private final Supplier defaultValue; - public DefaultedContextKey(ResourceLocation name, Supplier defaultValue) { + public DefaultedContextKey(Identifier name, Supplier defaultValue) { super(name); this.defaultValue = defaultValue; diff --git a/common/src/main/java/io/wispforest/accessories/api/client/renderers/AccessoryRenderer.java b/common/src/main/java/io/wispforest/accessories/api/client/renderers/AccessoryRenderer.java index d4cbcedfa..95631bf75 100644 --- a/common/src/main/java/io/wispforest/accessories/api/client/renderers/AccessoryRenderer.java +++ b/common/src/main/java/io/wispforest/accessories/api/client/renderers/AccessoryRenderer.java @@ -72,7 +72,7 @@ default boolean shouldCreateStackRenderState() { /// with [AccessoriesRenderStateKeys#ARM] /// default boolean shouldRender(ItemStack stack, SlotPath path, AccessoriesStorageLookup storageLookup, LivingEntity entity, LivingEntityRenderState entityState, boolean isRenderingEnabled) { - if (entityState.hasStateData(AccessoriesRenderStateKeys.ARM)) { + if (((io.wispforest.accessories.pond.AccessoriesRenderStateAPImpl) entityState).hasStateData(AccessoriesRenderStateKeys.ARM)) { return false; } diff --git a/common/src/main/java/io/wispforest/accessories/api/client/renderers/BuiltinAccessoryRenderers.java b/common/src/main/java/io/wispforest/accessories/api/client/renderers/BuiltinAccessoryRenderers.java index 6f1766722..7ef9858ba 100644 --- a/common/src/main/java/io/wispforest/accessories/api/client/renderers/BuiltinAccessoryRenderers.java +++ b/common/src/main/java/io/wispforest/accessories/api/client/renderers/BuiltinAccessoryRenderers.java @@ -25,7 +25,7 @@ import net.minecraft.client.renderer.entity.state.LivingEntityRenderState; import net.minecraft.client.renderer.texture.OverlayTexture; import net.minecraft.core.component.DataComponents; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.item.Item; @@ -71,8 +71,8 @@ public void render( private static , A extends HumanoidModel> void rendererArmor(HumanoidArmorLayer armorLayer, ItemStack stack, PoseStack poseStack, SubmitNodeCollector submitNodeCollector, S renderState, EquipmentSlot equipmentSlot) { var armorLayerAccessor = (HumanoidArmorLayerAccessor) armorLayer; - var light = renderState.getStateData(AccessoriesRenderStateKeys.LIGHT); - var partialTicks = renderState.getStateData(AccessoriesRenderStateKeys.PARTIAL_TICKS); + var light = ((io.wispforest.accessories.pond.AccessoriesRenderStateAPImpl) renderState).getStateData(AccessoriesRenderStateKeys.LIGHT); + var partialTicks = ((io.wispforest.accessories.pond.AccessoriesRenderStateAPImpl) renderState).getStateData(AccessoriesRenderStateKeys.PARTIAL_TICKS); if (!attemptGeckoRender(stack, poseStack, submitNodeCollector, renderState, equipmentSlot, light, partialTicks, armorLayer.getParentModel())) { armorLayerAccessor.accessories$renderArmorPiece(poseStack, submitNodeCollector, stack, equipmentSlot, light, renderState); @@ -104,7 +104,7 @@ public void render(AccessoryRenderState acce .filter(renderLayer -> renderLayer instanceof WingsLayer) .findFirst(); - var light = entityState.getStateData(AccessoriesRenderStateKeys.LIGHT); + var light = ((io.wispforest.accessories.pond.AccessoriesRenderStateAPImpl) entityState).getStateData(AccessoriesRenderStateKeys.LIGHT); possibleLayer.ifPresent(layer -> ((WingsLayerExtension) layer).renderStack(stack, matrices, collector, light, humanoidRenderState)); } @@ -124,10 +124,10 @@ public void render(AccessoryRenderState acce if (data == null || data.renderingFunctions() == null) return; - var light = entityState.getStateData(AccessoriesRenderStateKeys.LIGHT); - var partialTicks = entityState.getStateData(AccessoriesRenderStateKeys.PARTIAL_TICKS); + var light = ((io.wispforest.accessories.pond.AccessoriesRenderStateAPImpl) entityState).getStateData(AccessoriesRenderStateKeys.LIGHT); + var partialTicks = ((io.wispforest.accessories.pond.AccessoriesRenderStateAPImpl) entityState).getStateData(AccessoriesRenderStateKeys.PARTIAL_TICKS); - RenderingFunctionOps.handleFunctions(stack, path, matrices, model, entityState, collector, light, partialTicks, entityState.getStateData(AccessoriesRenderStateKeys.ARM), 15728880, OverlayTexture.NO_OVERLAY, -1, data.renderingFunctions()); + RenderingFunctionOps.handleFunctions(stack, path, matrices, model, entityState, collector, light, partialTicks, ((io.wispforest.accessories.pond.AccessoriesRenderStateAPImpl) entityState).getStateData(AccessoriesRenderStateKeys.ARM), 15728880, OverlayTexture.NO_OVERLAY, -1, data.renderingFunctions()); } @Override @@ -146,16 +146,14 @@ public static class BundleAccessoryRenderer implements AccessoryNestRenderer { public List getInnerStacks(ItemStack holderStack) { var contents = holderStack.get(DataComponents.BUNDLE_CONTENTS); - var items = contents.items(); - - return (items instanceof List stacks) ? stacks : Streams.stream(items).toList(); + return contents.itemCopyStream().toList(); } } - public static final ResourceLocation BUNDLE_RENDERER_ID = Accessories.of("bundle_renderer"); - public static final ResourceLocation DEFAULT_RENDERER_ID = Accessories.of("default_renderer"); - public static final ResourceLocation ARMOR_RENDERER_ID = Accessories.of("armor_renderer"); - public static final ResourceLocation ELYTRA_RENDERER_ID = Accessories.of("elytra_renderer"); + public static final Identifier BUNDLE_RENDERER_ID = Accessories.of("bundle_renderer"); + public static final Identifier DEFAULT_RENDERER_ID = Accessories.of("default_renderer"); + public static final Identifier ARMOR_RENDERER_ID = Accessories.of("armor_renderer"); + public static final Identifier ELYTRA_RENDERER_ID = Accessories.of("elytra_renderer"); static { AccessoriesRendererRegistry.bindItemToRenderer(Items.BUNDLE, BUNDLE_RENDERER_ID, BundleAccessoryRenderer::new); diff --git a/common/src/main/java/io/wispforest/accessories/api/client/renderers/DefaultAccessoryRenderer.java b/common/src/main/java/io/wispforest/accessories/api/client/renderers/DefaultAccessoryRenderer.java index f9f85ef29..f6290e6af 100644 --- a/common/src/main/java/io/wispforest/accessories/api/client/renderers/DefaultAccessoryRenderer.java +++ b/common/src/main/java/io/wispforest/accessories/api/client/renderers/DefaultAccessoryRenderer.java @@ -72,7 +72,7 @@ public void render(AccessoryRenderState acce throw new IllegalStateException("Unable to render default accessory as the ItemStacks render state has not been setup!"); } - var light = entityState.getStateData(AccessoriesRenderStateKeys.LIGHT); + var light = ((io.wispforest.accessories.pond.AccessoriesRenderStateAPImpl) entityState).getStateData(AccessoriesRenderStateKeys.LIGHT); Consumer renderCall = (poseStack) -> stackRenderState.submit(poseStack, collector, light, OverlayTexture.NO_OVERLAY, entityState.outlineColor); @@ -113,7 +113,7 @@ public boolean shouldRender(ItemStack stack, SlotPath path, AccessoriesStorageLo return false; } - var arm = renderState.getStateData(AccessoriesRenderStateKeys.ARM); + var arm = ((io.wispforest.accessories.pond.AccessoriesRenderStateAPImpl) renderState).getStateData(AccessoriesRenderStateKeys.ARM); if (arm != null) { return (slotName.equals("hand") || slotName.equals("wrist") || slotName.equals("ring")) diff --git a/common/src/main/java/io/wispforest/accessories/api/client/renderers/SimpleAccessoryRenderer.java b/common/src/main/java/io/wispforest/accessories/api/client/renderers/SimpleAccessoryRenderer.java index 8cd2c6ab1..ceb426956 100644 --- a/common/src/main/java/io/wispforest/accessories/api/client/renderers/SimpleAccessoryRenderer.java +++ b/common/src/main/java/io/wispforest/accessories/api/client/renderers/SimpleAccessoryRenderer.java @@ -29,14 +29,14 @@ default void render(AccessoryRenderState acc align(accessoryState, entityState, model, matrices); - var light = entityState.getStateData(AccessoriesRenderStateKeys.LIGHT); + var light = ((io.wispforest.accessories.pond.AccessoriesRenderStateAPImpl) entityState).getStateData(AccessoriesRenderStateKeys.LIGHT); var stack = accessoryState.getStateData(AccessoriesRenderStateKeys.ITEM_STACK); renderStack(accessoryState, entityState, model, matrices, collector, stack, stackRenderState, light); } public default void renderStack(AccessoryRenderState accessoryState, S entityState, EntityModel model, PoseStack matrices, SubmitNodeCollector collector, ItemStack stack, ItemStackRenderState stackRenderState, int light) { - stackRenderState.submit(matrices, collector, entityState.getStateData(AccessoriesRenderStateKeys.LIGHT), OverlayTexture.NO_OVERLAY, 0); + stackRenderState.submit(matrices, collector, ((io.wispforest.accessories.pond.AccessoriesRenderStateAPImpl) entityState).getStateData(AccessoriesRenderStateKeys.LIGHT), OverlayTexture.NO_OVERLAY, 0); } @Override diff --git a/common/src/main/java/io/wispforest/accessories/api/client/rendering/ModelTransformOps.java b/common/src/main/java/io/wispforest/accessories/api/client/rendering/ModelTransformOps.java index 246a22e89..4fe58963f 100644 --- a/common/src/main/java/io/wispforest/accessories/api/client/rendering/ModelTransformOps.java +++ b/common/src/main/java/io/wispforest/accessories/api/client/rendering/ModelTransformOps.java @@ -7,7 +7,7 @@ import net.minecraft.client.model.Model; import net.minecraft.client.model.geom.ModelPart; import net.minecraft.client.renderer.entity.state.LivingEntityRenderState; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.util.Mth; import net.minecraft.world.phys.Vec3; import org.jetbrains.annotations.ApiStatus; @@ -22,10 +22,10 @@ @ApiStatus.Experimental public class ModelTransformOps { - private static final Map ADDITIONAL_TRANSFORMERS = new LinkedHashMap<>(); + private static final Map ADDITIONAL_TRANSFORMERS = new LinkedHashMap<>(); @ApiStatus.Experimental - public static void registerTransformer(ResourceLocation location, ModelPartTransformer modelTransformers) { + public static void registerTransformer(Identifier location, ModelPartTransformer modelTransformers) { if (ADDITIONAL_TRANSFORMERS.containsKey(location)) { throw new IllegalStateException("Already existing ModelTransformer exists!"); } diff --git a/common/src/main/java/io/wispforest/accessories/api/client/rendering/RenderingFunction.java b/common/src/main/java/io/wispforest/accessories/api/client/rendering/RenderingFunction.java index 29bd7b0cd..056e82f65 100644 --- a/common/src/main/java/io/wispforest/accessories/api/client/rendering/RenderingFunction.java +++ b/common/src/main/java/io/wispforest/accessories/api/client/rendering/RenderingFunction.java @@ -22,7 +22,7 @@ import net.minecraft.core.particles.ParticleTypes; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.nbt.CompoundTag; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.world.entity.EntitySpawnReason; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.HumanoidArm; @@ -45,7 +45,7 @@ static Transformations ofTransformation(List e return Accessories.handleIoError("rendering_function_entity_data", scopedCollector -> { var valueOutput = TagValueOutput.createWithContext(scopedCollector, level.registryAccess()); - var string = entity.getEncodeId(); - if (string == null) throw new IllegalStateException("Unable to create render function of the given entity"); + var entityId = net.minecraft.core.registries.BuiltInRegistries.ENTITY_TYPE.getKey(entity.getType()); + if (entityId == null) throw new IllegalStateException("Unable to create render function of the given entity"); + var string = entityId.toString(); valueOutput.putString("id", string); entity.saveWithoutId(valueOutput); @@ -100,7 +101,7 @@ static Entity ofEntity(EntityType e return new Entity(entityType, data, true); } - static Particle ofParticle(ResourceLocation uniqueId, float delay, ParticleOptions particleData, Vector3f delta, float speed, int count, boolean overrideLimiter, boolean alwaysShow) { + static Particle ofParticle(Identifier uniqueId, float delay, ParticleOptions particleData, Vector3f delta, float speed, int count, boolean overrideLimiter, boolean alwaysShow) { return new Particle(uniqueId, delay, particleData, delta, speed, count, overrideLimiter, alwaysShow); } @@ -137,7 +138,7 @@ record Transformations(List ENDEC = StructEndecBuilder.of( MinecraftEndecs.IDENTIFIER.fieldOf("id", Model::id), Model::new @@ -183,7 +184,7 @@ record Entity(EntityType entityType, CompoundTag data, boolean allowTicking) ); } - record Particle(ResourceLocation uniqueId, float delay, ParticleOptions particleData, Vector3f delta, float speed, int count, boolean overrideLimiter, boolean alwaysShow) implements RenderingFunction { + record Particle(Identifier uniqueId, float delay, ParticleOptions particleData, Vector3f delta, float speed, int count, boolean overrideLimiter, boolean alwaysShow) implements RenderingFunction { private static final Endec PARTICLE_OPTIONS_ENDEC = CodecUtils.toEndec(ParticleTypes.CODEC); public static final StructEndec ENDEC = StructEndecBuilder.of( @@ -317,13 +318,13 @@ final class DeferredRenderer implements RenderingFunction, ArmedTargeted { DeferredRenderer::new ); - private final ResourceLocation rendererId; + private final Identifier rendererId; private final Map references; private final ArmTarget firstPersonArmTarget; private final UUID uuid; - public DeferredRenderer(ResourceLocation rendererId, + public DeferredRenderer(Identifier rendererId, Map references, ArmTarget firstPersonArmTarget) { this.rendererId = rendererId; @@ -334,7 +335,7 @@ public DeferredRenderer(ResourceLocation rendererId, } public Map references() { return Collections.unmodifiableMap(references); } - public ResourceLocation rendererId() { return rendererId; } + public Identifier rendererId() { return rendererId; } public ArmTarget firstPersonArmTarget() { return firstPersonArmTarget; } public UUID getUUID() { return uuid; } diff --git a/common/src/main/java/io/wispforest/accessories/api/client/rendering/RenderingFunctionOps.java b/common/src/main/java/io/wispforest/accessories/api/client/rendering/RenderingFunctionOps.java index 17ee956bd..0d8f7d2b3 100644 --- a/common/src/main/java/io/wispforest/accessories/api/client/rendering/RenderingFunctionOps.java +++ b/common/src/main/java/io/wispforest/accessories/api/client/rendering/RenderingFunctionOps.java @@ -15,7 +15,7 @@ import net.minecraft.client.renderer.SubmitNodeCollector; import net.minecraft.client.renderer.entity.state.LivingEntityRenderState; import net.minecraft.client.renderer.item.ItemStackRenderState; -import net.minecraft.client.renderer.state.CameraRenderState; +import net.minecraft.client.renderer.state.level.CameraRenderState; import net.minecraft.core.BlockPos; import net.minecraft.core.component.DataComponents; import net.minecraft.nbt.CompoundTag; @@ -61,7 +61,7 @@ public static void handleFunction(int uniqueKey, ItemStack stack, SlotPath path, var level = client.level; // var targetEntity = reference.entity(); - var cameraState = renderState.getStateData(AccessoriesRenderStateKeys.CAMERA_STATE); + var cameraState = ((io.wispforest.accessories.pond.AccessoriesRenderStateAPImpl) renderState).getStateData(AccessoriesRenderStateKeys.CAMERA_STATE); switch (renderingFunction) { case RenderingFunction.Transformations transformation -> { @@ -172,9 +172,10 @@ public static void handleFunction(int uniqueKey, ItemStack stack, SlotPath path, case RenderingFunction.Particle particleData -> { if (!PARTICLE_UPDATE_CACHE.hasAllottedTime(new ParticleTimeKey(((AccessoriesRenderStateAPI) renderState).getEntityUUIDForState(), uniqueKey, particleData), particleData.delay())) return; + var cameraPos = Minecraft.getInstance().gameRenderer.getMainCamera().position(); var pos = new Vector3f(0, 0, 0) .mulPosition(matrices.last().pose()) - .add(Minecraft.getInstance().gameRenderer.getMainCamera().getPosition().toVector3f()); + .add((float) cameraPos.x, (float) cameraPos.y, (float) cameraPos.z); renderParticle(level, particleData, pos.x(), pos.y(), pos.z()); } @@ -195,7 +196,7 @@ public static void handleFunction(int uniqueKey, ItemStack stack, SlotPath path, if(renderFunction == null) return; - var lookup = renderState.getStateData(AccessoriesRenderStateKeys.STORAGE_LOOKUP); + var lookup = ((io.wispforest.accessories.pond.AccessoriesRenderStateAPImpl) renderState).getStateData(AccessoriesRenderStateKeys.STORAGE_LOOKUP); renderFunction.ifLeft(accessoryRenderer -> { try { @@ -245,7 +246,10 @@ private static void renderParticle(Level level, RenderingFunction.Particle parti private static void renderBlock(Minecraft client, BlockState state, @Nullable BlockEntity blockEntity, CameraRenderState cameraState, float partialTick, PoseStack matrices, SubmitNodeCollector collector, int packedLight, int packedOverlay, int color) { if (state.getRenderShape() != RenderShape.INVISIBLE) { - collector.submitBlock(matrices, state, packedLight, packedOverlay, 0); + var blockStateModel = client.getModelManager().getBlockStateModelSet().get(state); + var parts = new java.util.ArrayList(); + blockStateModel.collectParts(net.minecraft.util.RandomSource.create(), parts); + collector.submitBlockModel(matrices, net.minecraft.client.renderer.rendertype.RenderTypes.solidMovingBlock(), parts, new int[0], packedLight, packedOverlay, 0); } if (blockEntity != null) { @@ -365,8 +369,8 @@ public static boolean shouldRender(ItemStack stack, SlotPath path, AccessoriesSt @Nullable public static Boolean shouldRender(ItemStack stack, SlotPath path, AccessoriesStorageLookup storageLookup, LivingEntity entity, LivingEntityRenderState entityState, RenderingFunction renderingFunction) { - if (renderingFunction instanceof RenderingFunction.ArmedTargeted armedTargeted && entityState.hasStateData(AccessoriesRenderStateKeys.ARM)) { - if (armedTargeted.firstPersonArmTarget().hasArm(entityState.getStateData(AccessoriesRenderStateKeys.ARM))) return true; + if (renderingFunction instanceof RenderingFunction.ArmedTargeted armedTargeted && ((io.wispforest.accessories.pond.AccessoriesRenderStateAPImpl) entityState).hasStateData(AccessoriesRenderStateKeys.ARM)) { + if (armedTargeted.firstPersonArmTarget().hasArm(((io.wispforest.accessories.pond.AccessoriesRenderStateAPImpl) entityState).getStateData(AccessoriesRenderStateKeys.ARM))) return true; } return switch (renderingFunction) { diff --git a/common/src/main/java/io/wispforest/accessories/api/client/screen/AccessoriesScreenTransitionHelper.java b/common/src/main/java/io/wispforest/accessories/api/client/screen/AccessoriesScreenTransitionHelper.java index 0b6d2973f..2f21be07c 100644 --- a/common/src/main/java/io/wispforest/accessories/api/client/screen/AccessoriesScreenTransitionHelper.java +++ b/common/src/main/java/io/wispforest/accessories/api/client/screen/AccessoriesScreenTransitionHelper.java @@ -15,9 +15,9 @@ import net.minecraft.client.gui.screens.inventory.InventoryScreen; import net.minecraft.client.player.LocalPlayer; import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.animal.horse.AbstractHorse; +import net.minecraft.world.entity.animal.equine.AbstractHorse; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; import org.jetbrains.annotations.ApiStatus; @@ -39,7 +39,7 @@ public class AccessoriesScreenTransitionHelper { private static final List>> SCREEN_CLASSES = new ArrayList<>(); - private static final Map BUTTON_INJECTION_DATA = new HashMap<>(); + private static final Map BUTTON_INJECTION_DATA = new HashMap<>(); private static final Map>, ScreenTransitionHelper> SCREEN_PREDICATES = new LinkedHashMap<>(); @@ -60,21 +60,21 @@ public static void registerScreensForButton(Class> void registerPlayerScreenTransition(ResourceLocation location, Class screenClass) { + public static > void registerPlayerScreenTransition(Identifier location, Class screenClass) { registerPlayerScreenTransition(location, screenClass::isInstance); registerScreensForButton(screenClass); } - public static void registerPlayerScreenTransition(ResourceLocation location, Predicate> screenPredicate) { + public static void registerPlayerScreenTransition(Identifier location, Predicate> screenPredicate) { registerScreenTransition(location, screenPredicate, ScreenBasedTargetGetter.PLAYER_DEFAULTED_TARGET, ScreenReopener.PLAYER_INVENTORY); } - public static > void registerScreenTransitionWithCustomInvReopener(ResourceLocation location, Class screenClass, ScreenBasedTargetGetter getter) { + public static > void registerScreenTransitionWithCustomInvReopener(Identifier location, Class screenClass, ScreenBasedTargetGetter getter) { registerScreenTransition(location, screenClass, getter, (ScreenReopener) ScreenReopener.CUSTOM_INVENTORY); } - public static > void registerScreenTransition(ResourceLocation location, Class screenClass, ScreenBasedTargetGetter getter, ScreenReopener reopener) { + public static > void registerScreenTransition(Identifier location, Class screenClass, ScreenBasedTargetGetter getter, ScreenReopener reopener) { registerScreenTransition(location, screenClass::isInstance, (ScreenBasedTargetGetter>) getter, @@ -83,7 +83,7 @@ public static > screenPredicate, ScreenBasedTargetGetter> targetEntityGetter, ScreenReopener> reopener) { + public static void registerScreenTransition(Identifier location, Predicate> screenPredicate, ScreenBasedTargetGetter> targetEntityGetter, ScreenReopener> reopener) { SCREEN_PREDICATES.put(screenPredicate, new ScreenTransitionHelper(location, targetEntityGetter, reopener)); } @@ -185,13 +185,13 @@ public static void openPrevScreen(Player player, LivingEntity targetEntity, @Nul @ApiStatus.Internal public static void init() { - registerPlayerScreenTransition(ResourceLocation.withDefaultNamespace("creative_player_inventory"), CreativeModeInventoryScreen.class); - registerPlayerScreenTransition(ResourceLocation.withDefaultNamespace("player_inventory"), InventoryScreen.class); + registerPlayerScreenTransition(Identifier.withDefaultNamespace("creative_player_inventory"), CreativeModeInventoryScreen.class); + registerPlayerScreenTransition(Identifier.withDefaultNamespace("player_inventory"), InventoryScreen.class); //-- registerScreenTransitionWithCustomInvReopener( - ResourceLocation.withDefaultNamespace("horse_inventory"), + Identifier.withDefaultNamespace("horse_inventory"), HorseInventoryScreen.class, (HorseInventoryScreen screen) -> ((HorseInventoryMenuAccessor) screen.getMenu()).accessories$horse() ); @@ -221,9 +221,9 @@ public static void initInjections() { INITIALIZED_INJECTIONS = true; } - private record ScreenTransitionHelper(ResourceLocation location, ScreenBasedTargetGetter> getter, ScreenReopener> reopener) { } + private record ScreenTransitionHelper(Identifier location, ScreenBasedTargetGetter> getter, ScreenReopener> reopener) { } public interface MenuButtonInjectionCallback { - void registerInjections(BiConsumer registerFunc); + void registerInjections(BiConsumer registerFunc); } } diff --git a/common/src/main/java/io/wispforest/accessories/api/client/tooltip/ClientTooltipComponentHolder.java b/common/src/main/java/io/wispforest/accessories/api/client/tooltip/ClientTooltipComponentHolder.java new file mode 100644 index 000000000..054bd7c50 --- /dev/null +++ b/common/src/main/java/io/wispforest/accessories/api/client/tooltip/ClientTooltipComponentHolder.java @@ -0,0 +1,10 @@ +package io.wispforest.accessories.api.client.tooltip; + +import io.wispforest.accessories.api.tooltip.TooltipComponentHolder; +import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent; + +import java.util.List; + +public interface ClientTooltipComponentHolder extends TooltipComponentHolder { + List components(); +} diff --git a/common/src/main/java/io/wispforest/accessories/api/client/tooltip/DeferredTooltip.java b/common/src/main/java/io/wispforest/accessories/api/client/tooltip/DeferredTooltip.java new file mode 100644 index 000000000..dce0f937b --- /dev/null +++ b/common/src/main/java/io/wispforest/accessories/api/client/tooltip/DeferredTooltip.java @@ -0,0 +1,25 @@ +package io.wispforest.accessories.api.client.tooltip; + +import net.minecraft.client.gui.Font; +import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent; +import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipPositioner; +import net.minecraft.resources.Identifier; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +public record DeferredTooltip( + Font font, + List components, + int x, + int y, + ClientTooltipPositioner positioner, + @Nullable Identifier background, + boolean focused, + Runnable runnable) implements Runnable, ClientTooltipComponentHolder { + + @Override + public void run() { + this.runnable.run(); + } +} diff --git a/common/src/main/java/io/wispforest/accessories/api/client/tooltip/TextWrapperImpl.java b/common/src/main/java/io/wispforest/accessories/api/client/tooltip/TextWrapperImpl.java new file mode 100644 index 000000000..7763896f1 --- /dev/null +++ b/common/src/main/java/io/wispforest/accessories/api/client/tooltip/TextWrapperImpl.java @@ -0,0 +1,52 @@ +package io.wispforest.accessories.api.client.tooltip; + +import io.wispforest.accessories.api.tooltip.TextWrapper; +import net.minecraft.client.Minecraft; +import net.minecraft.network.chat.FormattedText; +import net.minecraft.network.chat.Style; + +import java.util.Objects; +import java.util.stream.Stream; + +public final class TextWrapperImpl extends TextWrapper { + private final int maxWidth; + private final Style overrideStyle; + + public TextWrapperImpl(int maxWidth, Style overrideStyle) { + this.maxWidth = maxWidth; + this.overrideStyle = overrideStyle; + } + + public int maxWidth() { + return maxWidth; + } + + public Style overrideStyle() { + return overrideStyle; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) return true; + if (!(obj instanceof TextWrapperImpl other)) return false; + return this.maxWidth == other.maxWidth && + Objects.equals(this.overrideStyle, other.overrideStyle); + } + + @Override + public Stream wrap(FormattedText text) { + return Minecraft.getInstance().font.getSplitter().splitLines(text, maxWidth, overrideStyle).stream(); + } + + @Override + public int hashCode() { + return Objects.hash(maxWidth, overrideStyle); + } + + @Override + public String toString() { + return "TextWrapperImpl[" + + "maxWidth=" + maxWidth + ", " + + "overrideStyle=" + overrideStyle + ']';} + +} diff --git a/common/src/main/java/io/wispforest/accessories/api/client/tooltip/TooltipComponentBuilderImpl.java b/common/src/main/java/io/wispforest/accessories/api/client/tooltip/TooltipComponentBuilderImpl.java new file mode 100644 index 000000000..776de108b --- /dev/null +++ b/common/src/main/java/io/wispforest/accessories/api/client/tooltip/TooltipComponentBuilderImpl.java @@ -0,0 +1,141 @@ +package io.wispforest.accessories.api.client.tooltip; + +import io.wispforest.accessories.api.tooltip.*; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Font; +import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent; +import net.minecraft.locale.Language; +import net.minecraft.network.chat.FormattedText; +import org.jetbrains.annotations.ApiStatus; + +import java.util.*; +import java.util.function.Function; +import java.util.function.Supplier; +import java.util.stream.Stream; + +@ApiStatus.Internal +public class TooltipComponentBuilderImpl implements TooltipComponentBuilder { + + private final List components = new ArrayList<>(); + + private final List builtComponents = new ArrayList<>(); + private TextWrapper wrapper = TextWrapper.NONE; + private boolean hasBeenBuilt = false; + + private final Font font = Minecraft.getInstance().font; + private final Language lang = Language.getInstance(); + + public TooltipComponentBuilderImpl() {} + + private void resetCacheState() { + if (!hasBeenBuilt) return; + + hasBeenBuilt = false; + builtComponents.clear(); + } + + public void clear() { + resetCacheState(); + components.clear(); + } + + @Override + public TooltipComponentBuilder divider() { + return divider((int) Math.floor(font.lineHeight / 3f)); + } + + @Override + public TooltipComponentBuilder divider(int height) { + components.add((wrapper) -> Stream.of(spacer(height))); + + resetCacheState(); + + return this; + } + + @Override + public TooltipComponentBuilder add(FormattedText text) { + components.add((wrapper) -> wrapper.wrap(text).map(this::toComponent)); + + resetCacheState(); + + return this; + } + + @Override + public TooltipComponentBuilder add(TooltipComponentBuilder builder) { + if (!(builder instanceof TooltipComponentBuilderImpl impl)) { + throw new IllegalStateException("Unable to handle custom TooltipComponentBuilder type: " + builder.getClass().getName()); + } + + components.add(wrapper -> impl.build(wrapper).stream()); + + return this; + } + + @Override + public TooltipComponentBuilder addAll(Collection text) { + components.add((wrapper) -> text.stream().flatMap(wrapper::wrap).map(this::toComponent)); + + resetCacheState(); + + return this; + } + + @Override + public TooltipComponentBuilder addAll(TextPrefixer prefixer, FormattedTextBuilder builder) { + components.add((wrapper) -> builder.build(prefixer, wrapper).map(this::toComponent)); + + resetCacheState(); + + return this; + } + + public TooltipComponentBuilder add(TooltipComponentHolder holder) { + if (!(holder instanceof ClientTooltipComponentHolder clientHolder)) { + throw new IllegalStateException("Any class that extends directly from TooltipComponentHolder must be ClientTooltipComponent on the Client Side!"); + } + + components.add((wrapper) -> clientHolder.components().stream()); + + resetCacheState(); + + return this; + } + + @Override + public boolean isEmpty() { + return components.isEmpty(); + } + + public List build() { + return build(TextWrapper.NONE); + } + + public List build(TextWrapper wrapper) { + if (!hasBeenBuilt || !Objects.equals(this.wrapper, wrapper)) { + builtComponents.addAll(components.stream().flatMap(supplier -> supplier.get(wrapper)).toList()); + hasBeenBuilt = true; + this.wrapper = wrapper; + } + + return (!builtComponents.isEmpty()) + ? Collections.unmodifiableList(builtComponents) + : List.of(); + } + + private ClientTooltipComponent toComponent(FormattedText text) { + return ClientTooltipComponent.create(lang.getVisualOrder(text)); + } + + private static ClientTooltipComponent spacer(int height) { + return new ClientTooltipComponent() { + @Override public int getHeight(Font font) { return height;} + @Override public int getWidth(Font font) { return 1; } + }; + } + + private interface ComponentStreamSupplier { + Stream get(TextWrapper wrapper); + } +} diff --git a/common/src/main/java/io/wispforest/accessories/api/components/AccessoriesDataComponents.java b/common/src/main/java/io/wispforest/accessories/api/components/AccessoriesDataComponents.java index 0fff36705..ed2533a8a 100644 --- a/common/src/main/java/io/wispforest/accessories/api/components/AccessoriesDataComponents.java +++ b/common/src/main/java/io/wispforest/accessories/api/components/AccessoriesDataComponents.java @@ -6,7 +6,7 @@ import net.minecraft.core.Registry; import net.minecraft.core.component.DataComponentType; import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import org.jetbrains.annotations.ApiStatus; import java.util.function.UnaryOperator; @@ -39,7 +39,7 @@ public class AccessoriesDataComponents { builder -> builder.endec(AccessoryMobEffectsComponent.ENDEC, BASE_CTX) ); - private static DataComponentType register(ResourceLocation string, UnaryOperator> unaryOperator) { + private static DataComponentType register(Identifier string, UnaryOperator> unaryOperator) { return Registry.register(BuiltInRegistries.DATA_COMPONENT_TYPE, string, ((DataComponentType.Builder)unaryOperator.apply(DataComponentType.builder())).build()); } diff --git a/common/src/main/java/io/wispforest/accessories/api/components/AccessoryItemAttributeModifiers.java b/common/src/main/java/io/wispforest/accessories/api/components/AccessoryItemAttributeModifiers.java index 09c46949b..a9d373efd 100644 --- a/common/src/main/java/io/wispforest/accessories/api/components/AccessoryItemAttributeModifiers.java +++ b/common/src/main/java/io/wispforest/accessories/api/components/AccessoryItemAttributeModifiers.java @@ -4,6 +4,7 @@ import io.wispforest.accessories.Accessories; import io.wispforest.accessories.api.attributes.AccessoryAttributeBuilder; import io.wispforest.accessories.api.attributes.SlotAttribute; +import io.wispforest.accessories.api.data.AccessoriesBaseData; import io.wispforest.accessories.api.slot.SlotReference; import io.wispforest.accessories.api.slot.UniqueSlotHandling; import io.wispforest.accessories.data.SlotTypeLoader; @@ -15,7 +16,7 @@ import net.minecraft.core.Holder; import net.minecraft.core.registries.Registries; import net.minecraft.resources.ResourceKey; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.world.entity.ai.attributes.Attribute; import net.minecraft.world.entity.ai.attributes.AttributeModifier; import org.jetbrains.annotations.ApiStatus; @@ -40,12 +41,12 @@ public static AccessoryItemAttributeModifiers.Builder builder() { return new AccessoryItemAttributeModifiers.Builder(); } - public boolean hasModifier(Holder holder, ResourceLocation location) { + public boolean hasModifier(Holder holder, Identifier location) { return getModifier(holder, location) != null; } @Nullable - public AttributeModifier getModifier(Holder holder, ResourceLocation location) { + public AttributeModifier getModifier(Holder holder, Identifier location) { for (var entry : this.modifiers) { if(entry.attribute.equals(holder) && entry.modifier.id().equals(location)) return entry.modifier(); } @@ -54,7 +55,7 @@ public AttributeModifier getModifier(Holder holder, ResourceLocation } public AccessoryItemAttributeModifiers withModifierAddedForAny(Holder holder, AttributeModifier attributeModifier, boolean isStackable) { - return withModifierAdded(holder, attributeModifier, "any", isStackable); + return withModifierAdded(holder, attributeModifier, AccessoriesBaseData.ANY_SLOT, isStackable); } public AccessoryItemAttributeModifiers withModifierAdded(Holder holder, AttributeModifier attributeModifier, String slotName, boolean isStackable) { @@ -73,7 +74,7 @@ public AccessoryItemAttributeModifiers withModifierAdded(Holder holde return new AccessoryItemAttributeModifiers(builder.build(), this.showInTooltip()); } - public AccessoryItemAttributeModifiers withoutModifier(Holder holder, ResourceLocation location) { + public AccessoryItemAttributeModifiers withoutModifier(Holder holder, Identifier location) { var builder = ImmutableList.builderWithExpectedSize(this.modifiers.size() + 1); this.modifiers.forEach(entry -> { @@ -106,7 +107,7 @@ public AccessoryAttributeBuilder gatherAttributes(SlotReference slotReference, @ // OVERALL SHOULD BE BETTER INDICATE THAT THE USER DOSE NOT HAVE THE SLOT OR SOMETHING // if (slots.isEmpty() && !slots.containsKey(Accessories.parseLocationOrDefault(slotTarget))) continue; - if(slotReference.slotName().equals(slotTarget) || slotTarget.equals("any")) { + if(slotReference.slotName().equals(slotTarget) || slotTarget.equals(AccessoriesBaseData.ANY_SLOT)) { if (entry.isStackable()) { builder.addStackable(entry.attribute(), attributeModifier, entry.usedInSlotValidation()); } else { @@ -131,7 +132,7 @@ public AccessoryItemAttributeModifiers.Builder add(Holder holder, Att } public AccessoryItemAttributeModifiers.Builder addForAny(Holder holder, AttributeModifier attributeModifier, boolean isStackable) { - return addForSlot(holder, attributeModifier, "any", isStackable); + return addForSlot(holder, attributeModifier, AccessoriesBaseData.ANY_SLOT, isStackable); } public AccessoryItemAttributeModifiers.Builder addForSlot(Holder holder, AttributeModifier attributeModifier, String slotName, boolean isStackable) { @@ -187,13 +188,13 @@ public record Entry(Holder attribute, AttributeModifier modifier, Str } return context.requireAttributeValue(RegistriesAttribute.REGISTRIES) - .registryManager() + .registryAccess() .lookupOrThrow(Registries.ATTRIBUTE) .getKey(attribute); } ); - public boolean matches(Holder attribute, ResourceLocation id) { + public boolean matches(Holder attribute, Identifier id) { return attribute.equals(this.attribute) && this.modifier.is(id); } diff --git a/common/src/main/java/io/wispforest/accessories/api/components/AccessoryNestContainerContents.java b/common/src/main/java/io/wispforest/accessories/api/components/AccessoryNestContainerContents.java index 18fcec2bf..5d8691f1c 100644 --- a/common/src/main/java/io/wispforest/accessories/api/components/AccessoryNestContainerContents.java +++ b/common/src/main/java/io/wispforest/accessories/api/components/AccessoryNestContainerContents.java @@ -1,6 +1,7 @@ package io.wispforest.accessories.api.components; import io.wispforest.accessories.api.core.Accessory; +import io.wispforest.accessories.api.core.AccessoryNestUtils; import io.wispforest.accessories.api.core.AccessoryRegistry; import io.wispforest.accessories.api.events.SlotStateChange; import io.wispforest.accessories.api.slot.SlotEntryReference; @@ -122,6 +123,10 @@ public void iterateStacks(BiConsumer consumer) { } public @Nullable T iterateStacks(BiFunction function) { + return iterateStacks(function, (AccessoryNestUtils.DefaultBehavior) AccessoryNestUtils.DefaultBehavior.INSTANCE); + } + + public @Nullable T iterateStacks(BiFunction function, AccessoryNestUtils.DefaultBehavior behavior) { for (int i = 0; i < this.accessories.size(); i++) { var innerStack = this.accessories.get(i); @@ -129,7 +134,7 @@ public void iterateStacks(BiConsumer consumer) { var value = function.apply(i, innerStack); - if(value != null) break; + if(!behavior.isDefaulted(value)) break; } return null; diff --git a/common/src/main/java/io/wispforest/accessories/api/components/AccessorySlotValidationComponent.java b/common/src/main/java/io/wispforest/accessories/api/components/AccessorySlotValidationComponent.java index f1c01a7d2..261856be4 100644 --- a/common/src/main/java/io/wispforest/accessories/api/components/AccessorySlotValidationComponent.java +++ b/common/src/main/java/io/wispforest/accessories/api/components/AccessorySlotValidationComponent.java @@ -3,21 +3,37 @@ import io.wispforest.endec.Endec; import io.wispforest.endec.impl.StructEndecBuilder; -import java.util.HashSet; -import java.util.Set; +import java.util.*; -public record AccessorySlotValidationComponent(Set validSlotOverrides, Set invalidSlotOverrides) { +public record AccessorySlotValidationComponent(SequencedSet validSlotOverrides, SequencedSet invalidSlotOverrides) { public static final AccessorySlotValidationComponent EMPTY = new AccessorySlotValidationComponent(Set.of(), Set.of()); + @Deprecated + public AccessorySlotValidationComponent(Set validSlotOverrides, Set invalidSlotOverrides) { + this(new LinkedHashSet<>(validSlotOverrides), new LinkedHashSet<>(invalidSlotOverrides)); + } + + private static final Endec> STRING_SET_ENDEC = Endec.STRING.collectionOf(LinkedHashSet::new); + public static final Endec ENDEC = StructEndecBuilder.of( - Endec.STRING.setOf().optionalFieldOf("valid_slots", AccessorySlotValidationComponent::validSlotOverrides, Set::of), - Endec.STRING.setOf().optionalFieldOf("invalid_slots", AccessorySlotValidationComponent::invalidSlotOverrides, Set::of), + STRING_SET_ENDEC.optionalFieldOf("valid_slots", AccessorySlotValidationComponent::validSlotOverrides, LinkedHashSet::new), + STRING_SET_ENDEC.optionalFieldOf("invalid_slots", AccessorySlotValidationComponent::invalidSlotOverrides, LinkedHashSet::new), AccessorySlotValidationComponent::new ); + @Override + public SequencedSet validSlotOverrides() { + return Collections.unmodifiableSequencedSet(validSlotOverrides); + } + + @Override + public SequencedSet invalidSlotOverrides() { + return Collections.unmodifiableSequencedSet(invalidSlotOverrides); + } + public AccessorySlotValidationComponent addValidSlot(String slotName) { - var validSlotOverrides = new HashSet<>(this.validSlotOverrides); - var invalidSlotOverrides = new HashSet<>(this.invalidSlotOverrides); + var validSlotOverrides = new LinkedHashSet<>(this.validSlotOverrides); + var invalidSlotOverrides = new LinkedHashSet<>(this.invalidSlotOverrides); validSlotOverrides.add(slotName); invalidSlotOverrides.remove(slotName); @@ -26,8 +42,8 @@ public AccessorySlotValidationComponent addValidSlot(String slotName) { } public AccessorySlotValidationComponent addInvalidSlot(String slotName) { - var validSlotOverrides = new HashSet<>(this.validSlotOverrides); - var invalidSlotOverrides = new HashSet<>(this.invalidSlotOverrides); + var validSlotOverrides = new LinkedHashSet<>(this.validSlotOverrides); + var invalidSlotOverrides = new LinkedHashSet<>(this.invalidSlotOverrides); validSlotOverrides.remove(slotName); invalidSlotOverrides.add(slotName); @@ -36,7 +52,7 @@ public AccessorySlotValidationComponent addInvalidSlot(String slotName) { } public AccessorySlotValidationComponent removeValidSlot(String slotName) { - var validSlotOverrides = new HashSet<>(this.validSlotOverrides); + var validSlotOverrides = new LinkedHashSet<>(this.validSlotOverrides); validSlotOverrides.remove(slotName); @@ -44,10 +60,14 @@ public AccessorySlotValidationComponent removeValidSlot(String slotName) { } public AccessorySlotValidationComponent removeInvalidSlot(String slotName) { - var invalidSlotOverrides = new HashSet<>(this.invalidSlotOverrides); + var invalidSlotOverrides = new LinkedHashSet<>(this.invalidSlotOverrides); invalidSlotOverrides.remove(slotName); return new AccessorySlotValidationComponent(this.validSlotOverrides, invalidSlotOverrides); } + + public boolean isEmpty() { + return this.invalidSlotOverrides.isEmpty() && this.validSlotOverrides.isEmpty(); + } } diff --git a/common/src/main/java/io/wispforest/accessories/api/core/Accessory.java b/common/src/main/java/io/wispforest/accessories/api/core/Accessory.java index 5087a80e1..d712ae3c7 100644 --- a/common/src/main/java/io/wispforest/accessories/api/core/Accessory.java +++ b/common/src/main/java/io/wispforest/accessories/api/core/Accessory.java @@ -1,6 +1,9 @@ package io.wispforest.accessories.api.core; import io.wispforest.accessories.api.SoundEventData; +import io.wispforest.accessories.api.action.ActionResponse; +import io.wispforest.accessories.api.action.ActionResponseBuffer; +import io.wispforest.accessories.api.action.CurseBound; import io.wispforest.accessories.api.attributes.AccessoryAttributeBuilder; import io.wispforest.accessories.api.components.AccessoriesDataComponents; import io.wispforest.accessories.api.components.AccessoryItemAttributeModifiers; @@ -71,30 +74,33 @@ default void onUnequip(ItemStack stack, SlotReference reference){} * Used to indicate if the given Accessory can be equipped, such is invoked within {@link AccessoryRegistry#canEquip} * and is desired method to check if such can occur. * - * @param stack the stack to be equipped + * @param stack the stack to be equipped * @param reference the slot the accessory is in - * @return whether the given stack can be equipped + * @param buffer the buffer to send a response to if the Accessory can or can not be equipped */ @ApiStatus.OverrideOnly - default boolean canEquip(ItemStack stack, SlotReference reference){ - return true; + default void canEquip(ItemStack stack, SlotReference reference, ActionResponseBuffer buffer){ + if (canEquip(stack, reference)) return; + + buffer.respondWith(ActionResponse.of(false, Component.literal("Such an item can not be equipped!"))); } /** * Used to indicate if the given Accessory can be unequipped, such is invoked within {@link AccessoryRegistry#canUnequip} * and is desired method to check if such can occur. * - * @param stack the stack to be unequipped + * @param stack the stack to be unequipped * @param reference the slot the accessory is in - * @return whether the given stack can be unequipped + * @param buffer the buffer to send a response to if the Accessory can or can not be equipped */ @ApiStatus.OverrideOnly - default boolean canUnequip(ItemStack stack, SlotReference reference){ - if(EnchantmentHelper.has(stack, EnchantmentEffectComponents.PREVENT_ARMOR_CHANGE)) { - return reference.entity() instanceof Player player && player.isCreative(); - } + @MustBeInvokedByOverriders + default void canUnequip(ItemStack stack, SlotReference reference, ActionResponseBuffer buffer){ + if (CurseBound.checkIfCursed(stack, reference.entity(), buffer)) return; - return true; + if (canUnequip(stack, reference)) return; + + buffer.respondWith(ActionResponse.of(false, Component.literal("Such an item can not be unequipped!"))); } //-- @@ -297,4 +303,36 @@ default void getAttributesTooltip(ItemStack stack, SlotType type, List tooltips){} + + /** + * Used to indicate if the given Accessory can be equipped, such is invoked within {@link AccessoryRegistry#canEquip} + * and is desired method to check if such can occur. + * + * @param stack the stack to be equipped + * @param reference the slot the accessory is in + * @return whether the given stack can be equipped + */ + @Deprecated(forRemoval = true) + @ApiStatus.OverrideOnly + default boolean canEquip(ItemStack stack, SlotReference reference){ + return true; + } + + /** + * Used to indicate if the given Accessory can be unequipped, such is invoked within {@link AccessoryRegistry#canUnequip} + * and is desired method to check if such can occur. + * + * @param stack the stack to be unequipped + * @param reference the slot the accessory is in + * @return whether the given stack can be unequipped + */ + @Deprecated(forRemoval = true) + @ApiStatus.OverrideOnly + default boolean canUnequip(ItemStack stack, SlotReference reference){ + if(EnchantmentHelper.has(stack, EnchantmentEffectComponents.PREVENT_ARMOR_CHANGE)) { + return reference.entity() instanceof Player player && player.isCreative(); + } + + return true; + } } \ No newline at end of file diff --git a/common/src/main/java/io/wispforest/accessories/api/core/AccessoryNest.java b/common/src/main/java/io/wispforest/accessories/api/core/AccessoryNest.java index fd6147629..fef135ba1 100644 --- a/common/src/main/java/io/wispforest/accessories/api/core/AccessoryNest.java +++ b/common/src/main/java/io/wispforest/accessories/api/core/AccessoryNest.java @@ -1,5 +1,8 @@ package io.wispforest.accessories.api.core; +import io.wispforest.accessories.api.action.ActionResponse; +import io.wispforest.accessories.api.action.ActionResponseBuffer; +import io.wispforest.accessories.api.action.CurseBound; import io.wispforest.accessories.api.attributes.AccessoryAttributeBuilder; import io.wispforest.accessories.api.components.AccessoriesDataComponents; import io.wispforest.accessories.api.components.AccessoryNestContainerContents; @@ -144,21 +147,49 @@ default void onUnequip(ItemStack stack, SlotReference reference) { } @Override - default boolean canEquip(ItemStack stack, SlotReference reference) { - return handleEntries(stack, reference, (accessory, innerStack, innerRef) -> { - return (accessory.canEquip(innerStack, innerRef)) ? null : false; + default void canEquip(ItemStack stack, SlotReference reference, ActionResponseBuffer buffer) { + handleEntries(stack, reference, new PathedAccessoryFunction() { + @Override + public ActionResponseBuffer handle(Accessory accessory, ItemStack innerStack, SlotReference innerRef) { + accessory.canEquip(innerStack, innerRef, buffer); + + return buffer; + } + + @Override + public boolean isDefaulted(ActionResponseBuffer buffer) { + return buffer.shouldReturnEarly(); + } }); + + // TODO: REMOVE canEquip call WHEN DEPRECATION PHASE HAS BEEN LONG ENOUGH + if (buffer.shouldReturnEarly() || canEquip(stack, reference)) return; + + buffer.respondWith(ActionResponse.of(false, Component.literal("Such an item can not be equipped!"))); } @Override - default boolean canUnequip(ItemStack stack, SlotReference reference) { - if(EnchantmentHelper.has(stack, EnchantmentEffectComponents.PREVENT_ARMOR_CHANGE)) { - return reference.entity() instanceof Player player && player.isCreative(); - } + default void canUnequip(ItemStack stack, SlotReference reference, ActionResponseBuffer buffer) { + if (CurseBound.checkIfCursed(stack, reference.entity(), buffer)) return; - return handleEntries(stack, reference, (accessory, innerStack, innerRef) -> { - return (accessory.canUnequip(innerStack, innerRef)) ? null : false; + handleEntries(stack, reference, new PathedAccessoryFunction() { + @Override + public ActionResponseBuffer handle(Accessory accessory, ItemStack innerStack, SlotReference innerRef) { + accessory.canUnequip(innerStack, innerRef, buffer); + + return buffer; + } + + @Override + public boolean isDefaulted(ActionResponseBuffer buffer) { + return buffer.shouldReturnEarly(); + } }); + + // TODO: REMOVE canUnequip call WHEN DEPRECATION PHASE HAS BEEN LONG ENOUGH + if (buffer.shouldReturnEarly() || canUnequip(stack, reference)) return; + + buffer.respondWith(ActionResponse.of(false, Component.literal("Such an item can not be unequipped!"))); } @Override @@ -289,4 +320,18 @@ public boolean isDefaulted(TriState state) { } }).toBoolean(true); } + + @Override + default boolean canEquip(ItemStack stack, SlotReference reference) { + return true; + } + + @Override + default boolean canUnequip(ItemStack stack, SlotReference reference) { + if(EnchantmentHelper.has(stack, EnchantmentEffectComponents.PREVENT_ARMOR_CHANGE)) { + return reference.entity() instanceof Player player && player.isCreative(); + } + + return true; + } } diff --git a/common/src/main/java/io/wispforest/accessories/api/core/AccessoryNestUtils.java b/common/src/main/java/io/wispforest/accessories/api/core/AccessoryNestUtils.java index 113752724..e0a16400a 100644 --- a/common/src/main/java/io/wispforest/accessories/api/core/AccessoryNestUtils.java +++ b/common/src/main/java/io/wispforest/accessories/api/core/AccessoryNestUtils.java @@ -11,11 +11,6 @@ import net.minecraft.world.item.ItemStack; import org.jetbrains.annotations.Nullable; -import java.util.function.BiConsumer; -import java.util.function.BiFunction; -import java.util.function.Consumer; -import java.util.function.Function; - /// /// General utility for recursively handling and/or consuming the nest and/or their children entries. Basically /// a class for helping with unpacking data and attempting to interact with it safely @@ -98,7 +93,7 @@ public static boolean checkIfChangesOccurred(ItemStack holderStack, @Nullable Li var value = function.handle(accessory, stack, reference); - if (accessory instanceof AccessoryNest && value == null) { + if (accessory instanceof AccessoryNest && function.isDefaulted(value)) { value = handleEntries(stack, reference, (innerStack, innerRef) -> recursivelyHandle(innerStack, innerRef, function)); } @@ -115,9 +110,10 @@ public static boolean checkIfChangesOccurred(ItemStack holderStack, @Nullable Li var data = getData(stack); if (data != null) { - value = data.iterateStacks((i, innerStack) -> { - return function.handle(innerStack, SlotPath.cloneWithInnerIndex(reference, i)); - }); + value = data.iterateStacks( + (i, innerStack) -> function.handle(innerStack, SlotPath.cloneWithInnerIndex(reference, i)), + function + ); if (reference instanceof SlotReference ref) { checkIfChangesOccurred(stack, ref.entity(), data); @@ -170,18 +166,24 @@ public static void consumeEntries(ItemStack stack, S refere public static @Nullable T recursivelyHandle(ItemStack stack, AccessoryFunction function) { var accessory = AccessoryRegistry.getAccessoryOrDefault(stack); - function.handle(accessory, stack); + var value = function.handle(accessory, stack); - if (!(accessory instanceof AccessoryNest)) return null; + if (accessory instanceof AccessoryNest && function.isDefaulted(value)) { + value = handleEntries(stack, innerStack -> recursivelyHandle(innerStack, function), function); + } - return handleEntries(stack, innerStack -> recursivelyHandle(innerStack, function)); + return value; } public static @Nullable T handleEntries(ItemStack stack, AccessoryFunction function) { - return handleEntries(stack, (innerStack) -> function.handle(AccessoryRegistry.getAccessoryOrDefault(innerStack), innerStack)); + return handleEntries(stack, (innerStack) -> function.handle(AccessoryRegistry.getAccessoryOrDefault(innerStack), innerStack), function); } public static @Nullable T handleEntries(ItemStack stack, StackFunction function) { + return handleEntries(stack, function, (DefaultBehavior) DefaultBehavior.INSTANCE); + } + + public static @Nullable T handleEntries(ItemStack stack, StackFunction function, DefaultBehavior behavior) { var data = getData(stack); if (data == null) return null; @@ -193,7 +195,7 @@ public static void consumeEntries(ItemStack stack, S refere value = function.handle(innerStack); - if (value != null) break; + if (!behavior.isDefaulted(value)) break; } return value; @@ -231,7 +233,12 @@ public static void consumeEntries(ItemStack stack, StackConsumer consumer) { //-- + // TODO: MOVE ALL INTERFACES TO SUB FOLDER + + // TODO: RENAME TO SOMETHING ELSE BETTER? public interface DefaultBehavior { + static DefaultBehavior INSTANCE = new DefaultBehavior() {}; + default boolean isDefaulted(@Nullable T t) { return t == null; } diff --git a/common/src/main/java/io/wispforest/accessories/api/core/AccessoryRegistry.java b/common/src/main/java/io/wispforest/accessories/api/core/AccessoryRegistry.java index cc2d092f6..ebdc3bf2c 100644 --- a/common/src/main/java/io/wispforest/accessories/api/core/AccessoryRegistry.java +++ b/common/src/main/java/io/wispforest/accessories/api/core/AccessoryRegistry.java @@ -1,10 +1,14 @@ package io.wispforest.accessories.api.core; +import io.wispforest.accessories.api.action.ActionResponseBuffer; +import io.wispforest.accessories.api.action.ValidationState; import io.wispforest.accessories.api.components.AccessoriesDataComponents; -import io.wispforest.accessories.api.events.CanEquipCallback; -import io.wispforest.accessories.api.events.CanUnequipCallback; +import io.wispforest.accessories.api.events.v2.AllowEntityModificationCallback; +import io.wispforest.accessories.api.events.v2.CanEquipCallback; +import io.wispforest.accessories.api.events.v2.CanUnequipCallback; import io.wispforest.accessories.api.slot.SlotReference; import net.fabricmc.fabric.api.util.TriState; +import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import org.jetbrains.annotations.ApiStatus; @@ -80,11 +84,17 @@ public static boolean isDefaultAccessory(Accessory accessory) { * @return if the stack can be equipped or not */ public static boolean canEquip(ItemStack stack, SlotReference reference){ - var result = CanEquipCallback.EVENT.invoker().canEquip(stack, reference); + var buffer = new ActionResponseBuffer(true); - if(!result.equals(TriState.DEFAULT)) return result.orElse(true); + CanEquipCallback.EVENT.invoker().canEquip(stack, reference, buffer); - return getAccessoryOrDefault(stack).canEquip(stack, reference); + var state = buffer.canPerformAction(); + + if(!state.equals(ValidationState.IRRELEVANT)) return state.isValid(true); + + getAccessoryOrDefault(stack).canEquip(stack, reference, buffer); + + return buffer.canPerformAction().isValid(true); } /** @@ -95,13 +105,36 @@ public static boolean canEquip(ItemStack stack, SlotReference reference){ * @return if the stack can be unequipped or not */ public static boolean canUnequip(ItemStack stack, SlotReference reference){ - var result = CanUnequipCallback.EVENT.invoker().canUnequip(stack, reference); + var buffer = new ActionResponseBuffer(true); + + CanUnequipCallback.EVENT.invoker().canUnequip(stack, reference, buffer); - if(!result.equals(TriState.DEFAULT)) return result.orElse(true); + var state = buffer.canPerformAction(); - return getAccessoryOrDefault(stack).canUnequip(stack, reference); + if(!state.equals(ValidationState.IRRELEVANT)) return state.isValid(true); + + getAccessoryOrDefault(stack).canUnequip(stack, reference, buffer); + + return buffer.canPerformAction().isValid(true); } + public static ActionResponseBuffer canEquipResponse(ItemStack stack, SlotReference reference, ActionResponseBuffer buffer){ + CanEquipCallback.EVENT.invoker().canEquip(stack, reference, buffer); + + getAccessoryOrDefault(stack).canEquip(stack, reference, buffer); + + return buffer; + } + + public static ActionResponseBuffer canUnequipResponse(ItemStack stack, SlotReference reference, ActionResponseBuffer buffer){ + CanUnequipCallback.EVENT.invoker().canUnequip(stack, reference, buffer); + + getAccessoryOrDefault(stack).canUnequip(stack, reference, buffer); + + return buffer; + } + + //-- @ApiStatus.Internal diff --git a/common/src/main/java/io/wispforest/accessories/api/data/AccessoriesBaseData.java b/common/src/main/java/io/wispforest/accessories/api/data/AccessoriesBaseData.java index 8d918d6a6..3b3a5cb84 100644 --- a/common/src/main/java/io/wispforest/accessories/api/data/AccessoriesBaseData.java +++ b/common/src/main/java/io/wispforest/accessories/api/data/AccessoriesBaseData.java @@ -1,7 +1,11 @@ package io.wispforest.accessories.api.data; import io.wispforest.accessories.Accessories; -import net.minecraft.resources.ResourceLocation; +import io.wispforest.accessories.api.slot.SlotType; +import net.minecraft.resources.Identifier; + +import java.util.Collection; +import java.util.function.Supplier; // TODO: Rename to constants? public class AccessoriesBaseData { @@ -19,6 +23,16 @@ public class AccessoriesBaseData { public static final String SHOES_SLOT = "shoes"; public static final String WRIST_SLOT = "wrist"; + public static final String ANY_SLOT = "any"; + + public static boolean isValidSlotWithAny(Collection allowSlotNames, SlotType slotType) { + return isValidSlotWithAny(allowSlotNames, slotType::name); + } + + public static boolean isValidSlotWithAny(Collection allowSlotNames, Supplier slotName) { + return allowSlotNames.contains(AccessoriesBaseData.ANY_SLOT) || allowSlotNames.contains(slotName.get()); + } + public static final String MISC_GROUP = "misc"; public static final String HEAD_GROUP = "head"; public static final String CHEST_GROUP = "chest"; @@ -27,9 +41,9 @@ public class AccessoriesBaseData { public static final String FEET_GROUP = "feet"; public static final String UNSORTED_GROUP = "unsorted"; - public static final ResourceLocation ALL_PREDICATE_ID = Accessories.of("all"); - public static final ResourceLocation NONE_PREDICATE_ID = Accessories.of("none"); - public static final ResourceLocation TAG_PREDICATE_ID = Accessories.of("tag"); - public static final ResourceLocation ATTRIBUTE_PREDICATE_ID = Accessories.of("attribute"); - public static final ResourceLocation COMPONENT_PREDICATE_ID = Accessories.of("component"); + public static final Identifier ALL_PREDICATE_ID = Accessories.of("all"); + public static final Identifier NONE_PREDICATE_ID = Accessories.of("none"); + public static final Identifier TAG_PREDICATE_ID = Accessories.of("tag"); + public static final Identifier ATTRIBUTE_PREDICATE_ID = Accessories.of("attribute"); + public static final Identifier COMPONENT_PREDICATE_ID = Accessories.of("component"); } diff --git a/common/src/main/java/io/wispforest/accessories/api/data/AccessoriesTags.java b/common/src/main/java/io/wispforest/accessories/api/data/AccessoriesTags.java index fb737d5d0..52c3817a0 100644 --- a/common/src/main/java/io/wispforest/accessories/api/data/AccessoriesTags.java +++ b/common/src/main/java/io/wispforest/accessories/api/data/AccessoriesTags.java @@ -40,7 +40,7 @@ public class AccessoriesTags { * Slot tag used to allow for this given items contained inside to be * equipped to any slot if the such has the {@link AccessoriesBaseData#TAG_PREDICATE_ID} */ - public static final TagKey ANY_TAG = itemTag("any"); + public static final TagKey ANY_TAG = itemTag(ANY_SLOT); public static final TagKey VALID_GLIDER_EQUIP = itemTag("valid_glider_equip"); diff --git a/common/src/main/java/io/wispforest/accessories/api/data/providers/entity/EntityBindingProvider.java b/common/src/main/java/io/wispforest/accessories/api/data/providers/entity/EntityBindingProvider.java index 2d183c2dd..a577f489a 100644 --- a/common/src/main/java/io/wispforest/accessories/api/data/providers/entity/EntityBindingProvider.java +++ b/common/src/main/java/io/wispforest/accessories/api/data/providers/entity/EntityBindingProvider.java @@ -7,7 +7,7 @@ import net.minecraft.data.CachedOutput; import net.minecraft.data.DataProvider; import net.minecraft.data.PackOutput; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import java.util.ArrayList; import java.util.Collection; @@ -47,7 +47,7 @@ protected final PackOutput.Target target() { } public interface EntityBindingOutput extends BaseDataProvider.DataOutput { - void accept(ResourceLocation location, RawEntityBinding binding); + void accept(Identifier location, RawEntityBinding binding); } @Override @@ -57,7 +57,7 @@ protected EntityBindingOutput buildOutput(CachedOutput cachedOutput, HolderLooku final List> list = new ArrayList<>(); @Override - public void accept(ResourceLocation location, RawEntityBinding binding) { + public void accept(Identifier location, RawEntityBinding binding) { list.add(DataProvider.saveStable(cachedOutput, provider, CODEC, binding, EntityBindingProvider.this.pathProvider().json(location))); } diff --git a/common/src/main/java/io/wispforest/accessories/api/data/providers/entity/RawEntityBinding.java b/common/src/main/java/io/wispforest/accessories/api/data/providers/entity/RawEntityBinding.java index 7a557e223..ddf7f5530 100644 --- a/common/src/main/java/io/wispforest/accessories/api/data/providers/entity/RawEntityBinding.java +++ b/common/src/main/java/io/wispforest/accessories/api/data/providers/entity/RawEntityBinding.java @@ -6,7 +6,7 @@ import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.core.registries.Registries; import net.minecraft.resources.ResourceKey; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.tags.TagKey; import net.minecraft.world.entity.EntityType; @@ -32,11 +32,11 @@ public record RawEntityBinding(Optional replace, List set = Sets.newHashSet(); + final Set set = Sets.newHashSet(); final List> list = new ArrayList<>(); @Override public void accept(String namespace, RawSlotGroup rawSlotType) { - var location = ResourceLocation.fromNamespaceAndPath(namespace, rawSlotType.name().replace(":", "/")); + var location = Identifier.fromNamespaceAndPath(namespace, rawSlotType.name().replace(":", "/")); if (!set.add(location)) throw new IllegalStateException("Duplicate Group: " + location); diff --git a/common/src/main/java/io/wispforest/accessories/api/data/providers/group/RawSlotGroup.java b/common/src/main/java/io/wispforest/accessories/api/data/providers/group/RawSlotGroup.java index beffadfcb..0d4d2f780 100644 --- a/common/src/main/java/io/wispforest/accessories/api/data/providers/group/RawSlotGroup.java +++ b/common/src/main/java/io/wispforest/accessories/api/data/providers/group/RawSlotGroup.java @@ -4,12 +4,12 @@ import io.wispforest.endec.StructEndec; import io.wispforest.endec.impl.StructEndecBuilder; import io.wispforest.owo.serialization.endec.MinecraftEndecs; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import java.util.List; import java.util.Optional; -public record RawSlotGroup(String name, Optional replace, Optional icon, Optional order, Optional> slots) { +public record RawSlotGroup(String name, Optional replace, Optional icon, Optional order, Optional> slots) { public static final StructEndec ENDEC = StructEndecBuilder.of( Endec.STRING.fieldOf("name", RawSlotGroup::name), Endec.BOOLEAN.optionalOf().fieldOf("replace", RawSlotGroup::replace), diff --git a/common/src/main/java/io/wispforest/accessories/api/data/providers/group/SlotGroupBuilder.java b/common/src/main/java/io/wispforest/accessories/api/data/providers/group/SlotGroupBuilder.java index 223ac6918..3bced892c 100644 --- a/common/src/main/java/io/wispforest/accessories/api/data/providers/group/SlotGroupBuilder.java +++ b/common/src/main/java/io/wispforest/accessories/api/data/providers/group/SlotGroupBuilder.java @@ -1,7 +1,7 @@ package io.wispforest.accessories.api.data.providers.group; import io.wispforest.accessories.api.slot.UniqueSlotHandling; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import java.util.ArrayList; import java.util.List; @@ -14,7 +14,7 @@ public class SlotGroupBuilder { private final String name; private final boolean uniqueGroup; - private ResourceLocation icon = null; + private Identifier icon = null; private Integer order = null; private final List slots = new ArrayList<>(); @@ -32,7 +32,7 @@ public SlotGroupBuilder order(Integer value) { return this; } - public SlotGroupBuilder icon(ResourceLocation value) { + public SlotGroupBuilder icon(Identifier value) { this.icon = value; return this; } diff --git a/common/src/main/java/io/wispforest/accessories/api/data/providers/slot/RawSlotType.java b/common/src/main/java/io/wispforest/accessories/api/data/providers/slot/RawSlotType.java index 41432e94d..67570c01c 100644 --- a/common/src/main/java/io/wispforest/accessories/api/data/providers/slot/RawSlotType.java +++ b/common/src/main/java/io/wispforest/accessories/api/data/providers/slot/RawSlotType.java @@ -5,12 +5,12 @@ import io.wispforest.endec.StructEndec; import io.wispforest.endec.impl.StructEndecBuilder; import io.wispforest.owo.serialization.endec.MinecraftEndecs; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import java.util.Optional; import java.util.Set; -public record RawSlotType(String name, Optional replace, Optional icon, Optional order, Optional amount, Optional> validators, Optional dropRule) { +public record RawSlotType(String name, Optional replace, Optional icon, Optional order, Optional amount, Optional> validators, Optional dropRule) { public static final StructEndec ENDEC = StructEndecBuilder.of( Endec.STRING.fieldOf("name", RawSlotType::name), Endec.BOOLEAN.optionalOf().fieldOf("replace", RawSlotType::replace), diff --git a/common/src/main/java/io/wispforest/accessories/api/data/providers/slot/SlotBuilder.java b/common/src/main/java/io/wispforest/accessories/api/data/providers/slot/SlotBuilder.java index 934166431..e3110aeec 100644 --- a/common/src/main/java/io/wispforest/accessories/api/data/providers/slot/SlotBuilder.java +++ b/common/src/main/java/io/wispforest/accessories/api/data/providers/slot/SlotBuilder.java @@ -5,7 +5,7 @@ import io.wispforest.accessories.api.slot.UniqueSlotHandling; import io.wispforest.accessories.impl.slot.ExtraSlotTypeProperties; import io.wispforest.accessories.impl.slot.StrictMode; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import org.slf4j.Logger; import java.util.HashSet; @@ -21,13 +21,13 @@ public class SlotBuilder { private final String name; private final boolean uniqueSlot; - private ResourceLocation icon = null; + private Identifier icon = null; private Integer order = null; private Integer baseAmount = null; private Integer offsetAmount = 0; - private final Set validators = new HashSet<>(); + private final Set validators = new HashSet<>(); private DropRule dropRule = null; public SlotBuilder(String name, boolean replace) { @@ -38,7 +38,7 @@ public SlotBuilder(String name, boolean replace) { this.uniqueSlot = UniqueSlotHandling.isUniqueSlot(name); } - public SlotBuilder icon(ResourceLocation value) { + public SlotBuilder icon(Identifier value) { this.icon = value; return this; } @@ -84,7 +84,7 @@ public SlotBuilder subtractAmount(int value) { return this; } - public SlotBuilder validator(ResourceLocation validator) { + public SlotBuilder validator(Identifier validator) { if (this.uniqueSlot && !ExtraSlotTypeProperties.getProperty(this.name, false).strictMode().equals(StrictMode.NONE)) { LOGGER.error("[SlotDataProvider] An attempt to adjust the validators for a given Unique slot even though strict mode is enabled! [Slot: {}]", this.name); diff --git a/common/src/main/java/io/wispforest/accessories/api/data/providers/slot/SlotDataProvider.java b/common/src/main/java/io/wispforest/accessories/api/data/providers/slot/SlotDataProvider.java index fee1c1a16..f9fd83c23 100644 --- a/common/src/main/java/io/wispforest/accessories/api/data/providers/slot/SlotDataProvider.java +++ b/common/src/main/java/io/wispforest/accessories/api/data/providers/slot/SlotDataProvider.java @@ -8,7 +8,7 @@ import net.minecraft.data.CachedOutput; import net.minecraft.data.DataProvider; import net.minecraft.data.PackOutput; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import java.util.ArrayList; import java.util.Collection; @@ -31,7 +31,7 @@ public interface SlotOutput extends DataOutput { @Override protected abstract void buildData(HolderLookup.Provider provider, SlotOutput output); - public SlotBuilder builder(ResourceLocation uniqueLocation) { + public SlotBuilder builder(Identifier uniqueLocation) { return builder(uniqueLocation.toString()); } @@ -59,12 +59,12 @@ protected final PackOutput.Target target() { @Override protected final SlotOutput buildOutput(CachedOutput cachedOutput, HolderLookup.Provider provider) { return new SlotOutput() { - final Set set = Sets.newHashSet(); + final Set set = Sets.newHashSet(); final List> list = new ArrayList<>(); @Override public void accept(String namespace, RawSlotType rawSlotType) { - var location = ResourceLocation.fromNamespaceAndPath(namespace, rawSlotType.name().replace(":", "/")); + var location = Identifier.fromNamespaceAndPath(namespace, rawSlotType.name().replace(":", "/")); if (!set.add(location)) throw new IllegalStateException("Duplicate SlotType: " + location); diff --git a/common/src/main/java/io/wispforest/accessories/api/events/AllowEntityModificationCallback.java b/common/src/main/java/io/wispforest/accessories/api/events/AllowEntityModificationCallback.java index fd8e14ec0..01c6fb9ca 100644 --- a/common/src/main/java/io/wispforest/accessories/api/events/AllowEntityModificationCallback.java +++ b/common/src/main/java/io/wispforest/accessories/api/events/AllowEntityModificationCallback.java @@ -1,8 +1,13 @@ package io.wispforest.accessories.api.events; import io.wispforest.accessories.Accessories; +import io.wispforest.accessories.api.action.ActionResponseBuffer; +import io.wispforest.accessories.api.action.ValidationState; import io.wispforest.accessories.api.menu.AccessoriesBasedSlot; import io.wispforest.accessories.api.slot.SlotReference; +import io.wispforest.accessories.impl.core.UnknownResponse; +import io.wispforest.accessories.impl.event.WrappedEvent; +import io.wispforest.accessories.menu.AccessoriesMenuVariant; import net.fabricmc.fabric.api.event.Event; import net.fabricmc.fabric.api.event.EventFactory; import net.fabricmc.fabric.api.util.TriState; @@ -16,23 +21,28 @@ * screen being open by the given player. *

* Fired in {@link AccessoriesBasedSlot#mayPickup} - * and in {@link Accessories#openAccessoriesMenu(Player, LivingEntity, ItemStack)} + * and in {@link Accessories#openAccessoriesMenu(Player, AccessoriesMenuVariant, LivingEntity,ItemStack)} */ +@Deprecated public interface AllowEntityModificationCallback { - Event EVENT = EventFactory.createArrayBacked(AllowEntityModificationCallback.class, - (invokers) -> (targetEntity, player, reference) -> { - TriState returnResult = TriState.DEFAULT; + Event EVENT = new WrappedEvent<>( + io.wispforest.accessories.api.events.v2.AllowEntityModificationCallback.EVENT, + callback -> { + return (targetEntity, player, ref, buffer) -> { + var result = callback.allowModifications(targetEntity, player, ref); - for (var invoker : invokers) { - returnResult = invoker.allowModifications(targetEntity, player, reference); + buffer.respondWith(new UnknownResponse(ValidationState.of(result))); + }; + }, event -> { + return (targetEntity, player, reference) -> { + var buffer = new ActionResponseBuffer(true); - if(!returnResult.equals(TriState.DEFAULT)) break; - } + event.invoker().allowModifications(targetEntity, player, reference, buffer); - return returnResult; - } - ); + return buffer.canPerformAction().toTriState(); + }; + }); /** * @param targetEntity The targeted entity for modification diff --git a/common/src/main/java/io/wispforest/accessories/api/events/CanEquipCallback.java b/common/src/main/java/io/wispforest/accessories/api/events/CanEquipCallback.java index c6039999f..7344b04dc 100644 --- a/common/src/main/java/io/wispforest/accessories/api/events/CanEquipCallback.java +++ b/common/src/main/java/io/wispforest/accessories/api/events/CanEquipCallback.java @@ -1,41 +1,43 @@ package io.wispforest.accessories.api.events; +import io.wispforest.accessories.api.action.ActionResponseBuffer; +import io.wispforest.accessories.api.action.ValidationState; import io.wispforest.accessories.api.core.AccessoryNestUtils; import io.wispforest.accessories.api.core.AccessoryRegistry; import io.wispforest.accessories.api.slot.SlotReference; +import io.wispforest.accessories.impl.core.UnknownResponse; +import io.wispforest.accessories.impl.event.WrappedEvent; import net.fabricmc.fabric.api.event.Event; import net.fabricmc.fabric.api.event.EventFactory; import net.fabricmc.fabric.api.util.TriState; import net.minecraft.world.item.ItemStack; /// +/// @deprecated Use [io.wispforest.accessories.api.events.v2.CanEquipCallback] instead! /// Event callback used to allow or denied the ability to equip a given accessory for the given referenced slot /// type and entity. /// /// Fired in [AccessoryRegistry#canEquip(ItemStack,SlotReference)] /// +@Deprecated(forRemoval = true) public interface CanEquipCallback { - Event EVENT = EventFactory.createArrayBacked(CanEquipCallback.class, - (invokers) -> (stack, reference) -> { - var result = AccessoryNestUtils.recursivelyHandle(stack, reference, (innerStack, innerRef) -> { - TriState finalResult = null; + Event EVENT = new WrappedEvent<>( + io.wispforest.accessories.api.events.v2.CanEquipCallback.EVENT, + canEquipCallback -> (stack, reference, callback) -> { + var result = canEquipCallback.canEquip(stack, reference); - for (var invoker : invokers) { - var returnResult = invoker.canEquip(innerStack, innerRef); + if (result != TriState.DEFAULT) callback.respondWith(new UnknownResponse(ValidationState.of(result))); + }, + canEquipCallbackEvent -> { + return (stack, reference) -> { + var buffer = new ActionResponseBuffer(true); - if(returnResult.equals(TriState.FALSE)) { - finalResult = returnResult; + canEquipCallbackEvent.invoker().canEquip(stack, reference, buffer); - break; - } - } - - return finalResult; - }); - - return result != null ? result : TriState.DEFAULT; - } + return buffer.canPerformAction().toTriState(); + }; + } ); /// diff --git a/common/src/main/java/io/wispforest/accessories/api/events/CanUnequipCallback.java b/common/src/main/java/io/wispforest/accessories/api/events/CanUnequipCallback.java index d7bd30abe..1eef01c64 100644 --- a/common/src/main/java/io/wispforest/accessories/api/events/CanUnequipCallback.java +++ b/common/src/main/java/io/wispforest/accessories/api/events/CanUnequipCallback.java @@ -1,41 +1,42 @@ package io.wispforest.accessories.api.events; -import io.wispforest.accessories.api.core.AccessoryNestUtils; +import io.wispforest.accessories.api.action.ActionResponseBuffer; +import io.wispforest.accessories.api.action.ValidationState; import io.wispforest.accessories.api.core.AccessoryRegistry; import io.wispforest.accessories.api.slot.SlotReference; +import io.wispforest.accessories.impl.core.UnknownResponse; +import io.wispforest.accessories.impl.event.WrappedEvent; import net.fabricmc.fabric.api.event.Event; -import net.fabricmc.fabric.api.event.EventFactory; import net.fabricmc.fabric.api.util.TriState; import net.minecraft.world.item.ItemStack; +import org.apache.commons.lang3.mutable.MutableObject; /// +/// @deprecated Use [io.wispforest.accessories.api.events.v2.CanUnequipCallback] instead! /// Event callback used to allow or denied the ability to equip a given accessory for the given referenced slot /// type and entity. /// /// Fired in [AccessoryRegistry#canUnequip(ItemStack,SlotReference)] /// +@Deprecated(forRemoval = true) public interface CanUnequipCallback { - Event EVENT = EventFactory.createArrayBacked(CanUnequipCallback.class, - (invokers) -> (stack, reference) -> { - var result = AccessoryNestUtils.recursivelyHandle(stack, reference, (innerStack, innerRef) -> { - TriState finalResult = null; + Event EVENT = new WrappedEvent<>( + io.wispforest.accessories.api.events.v2.CanUnequipCallback.EVENT, + canEquipCallback -> (stack, reference, callback) -> { + var result = canEquipCallback.canUnequip(stack, reference); - for (var invoker : invokers) { - var returnResult = invoker.canUnequip(innerStack, innerRef); + if (result != TriState.DEFAULT) callback.respondWith(new UnknownResponse(ValidationState.of(result))); + }, + canEquipCallbackEvent -> { + return (stack, reference) -> { + var buffer = new ActionResponseBuffer(true); - if(returnResult.equals(TriState.FALSE)) { - finalResult = returnResult; + canEquipCallbackEvent.invoker().canUnequip(stack, reference, buffer); - break; - } - } - - return finalResult; - }); - - return result != null ? result : TriState.DEFAULT; - } + return buffer.canPerformAction().toTriState(); + }; + } ); /// @@ -44,4 +45,4 @@ public interface CanUnequipCallback { /// @return If the given stack can be unequipped /// TriState canUnequip(ItemStack stack, SlotReference reference); -} +} \ No newline at end of file diff --git a/common/src/main/java/io/wispforest/accessories/api/events/extra/ExtraEventHandler.java b/common/src/main/java/io/wispforest/accessories/api/events/extra/ExtraEventHandler.java index 0f7a7ac4d..3105ec9a8 100644 --- a/common/src/main/java/io/wispforest/accessories/api/events/extra/ExtraEventHandler.java +++ b/common/src/main/java/io/wispforest/accessories/api/events/extra/ExtraEventHandler.java @@ -167,7 +167,7 @@ public static TriState canFreezeEntity(LivingEntity entity){ .build(CacheLoader.from(() -> new HashMap<>())); public static TriState isGazedBlocked(LivingEntity lookingEntity, LivingEntity targetEntity){ - if (lookingEntity.getType().is(AccessoriesTags.GAZE_DISGUISED_BLACKLIST)) return TriState.DEFAULT; + if (lookingEntity.getType().builtInRegistryHolder().is(AccessoriesTags.GAZE_DISGUISED_BLACKLIST)) return TriState.DEFAULT; var cache = gazeDisguiseCache.getIfPresent(targetEntity.getId()); diff --git a/common/src/main/java/io/wispforest/accessories/api/events/v2/AllowEntityModificationCallback.java b/common/src/main/java/io/wispforest/accessories/api/events/v2/AllowEntityModificationCallback.java new file mode 100644 index 000000000..a7055594b --- /dev/null +++ b/common/src/main/java/io/wispforest/accessories/api/events/v2/AllowEntityModificationCallback.java @@ -0,0 +1,41 @@ +package io.wispforest.accessories.api.events.v2; + +import io.wispforest.accessories.Accessories; +import io.wispforest.accessories.api.action.ActionResponseBuffer; +import io.wispforest.accessories.api.menu.AccessoriesBasedSlot; +import io.wispforest.accessories.api.slot.SlotReference; +import io.wispforest.accessories.menu.AccessoriesMenuVariant; +import net.fabricmc.fabric.api.event.Event; +import net.fabricmc.fabric.api.event.EventFactory; +import net.fabricmc.fabric.api.util.TriState; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import org.jetbrains.annotations.Nullable; + +/// Event callback used to allow or denied the ability to adjust a given entities accessories or prevent the Accessory +/// screen being open by the given player. +/// +/// Fired in [AccessoriesBasedSlot#mayPickup] +/// and in [Accessories#openAccessoriesMenu(Player, AccessoriesMenuVariant, LivingEntity,ItemStack)] +/// +public interface AllowEntityModificationCallback { + + Event EVENT = EventFactory.createArrayBacked(AllowEntityModificationCallback.class, + (invokers) -> (targetEntity, player, reference, buffer) -> { + for (var invoker : invokers) { + invoker.allowModifications(targetEntity, player, reference, buffer); + + if(buffer.shouldReturnEarly()) return; + } + } + ); + + /// + /// @param targetEntity The targeted entity for modification + /// @param player The specific player + /// @param reference The reference to the specific location within the Accessories Inventory + /// @param buffer The buffer to send a response to if the Accessory can or can not be equipped + /// + void allowModifications(LivingEntity targetEntity, Player player, @Nullable SlotReference reference, ActionResponseBuffer buffer); +} diff --git a/common/src/main/java/io/wispforest/accessories/api/events/v2/CanEquipCallback.java b/common/src/main/java/io/wispforest/accessories/api/events/v2/CanEquipCallback.java new file mode 100644 index 000000000..10ecd127f --- /dev/null +++ b/common/src/main/java/io/wispforest/accessories/api/events/v2/CanEquipCallback.java @@ -0,0 +1,39 @@ +package io.wispforest.accessories.api.events.v2; + +import io.wispforest.accessories.api.action.ActionResponseBuffer; +import io.wispforest.accessories.api.core.AccessoryNestUtils; +import io.wispforest.accessories.api.core.AccessoryRegistry; +import io.wispforest.accessories.api.slot.SlotReference; +import net.fabricmc.fabric.api.event.Event; +import net.fabricmc.fabric.api.event.EventFactory; +import net.minecraft.world.item.ItemStack; + +/// +/// Event callback used to allow or denied the ability to equip a given accessory for the given referenced slot +/// type and entity. +/// +/// Fired in [AccessoryRegistry#canEquip(ItemStack,SlotReference)] +/// +public interface CanEquipCallback { + + Event EVENT = EventFactory.createArrayBacked(CanEquipCallback.class, + (invokers) -> (stack, reference, buffer) -> { + AccessoryNestUtils.recursivelyHandle(stack, reference, (stack1, reference1) -> { + for (var invoker : invokers) { + invoker.canEquip(stack1, reference1, buffer); + + if(buffer.shouldReturnEarly()) return true; + } + + return null; + }); + } + ); + + /// + /// @param stack The specific stack being evaluated + /// @param reference The reference to the specific location within the Accessories Inventory + /// @param buffer The buffer to send a response to if the Accessory can or can not be equipped + /// + void canEquip(ItemStack stack, SlotReference reference, ActionResponseBuffer buffer); +} diff --git a/common/src/main/java/io/wispforest/accessories/api/events/v2/CanUnequipCallback.java b/common/src/main/java/io/wispforest/accessories/api/events/v2/CanUnequipCallback.java new file mode 100644 index 000000000..baedebbd3 --- /dev/null +++ b/common/src/main/java/io/wispforest/accessories/api/events/v2/CanUnequipCallback.java @@ -0,0 +1,40 @@ +package io.wispforest.accessories.api.events.v2; + +import io.wispforest.accessories.api.action.ActionResponseBuffer; +import io.wispforest.accessories.api.core.AccessoryNestUtils; +import io.wispforest.accessories.api.core.AccessoryRegistry; +import io.wispforest.accessories.api.slot.SlotReference; +import net.fabricmc.fabric.api.event.Event; +import net.fabricmc.fabric.api.event.EventFactory; +import net.minecraft.world.item.ItemStack; +import org.apache.commons.lang3.mutable.MutableBoolean; + +/// +/// Event callback used to allow or denied the ability to equip a given accessory for the given referenced slot +/// type and entity. +/// +/// Fired in [AccessoryRegistry#canUnequip(ItemStack,SlotReference)] +/// +public interface CanUnequipCallback { + + Event EVENT = EventFactory.createArrayBacked(CanUnequipCallback.class, + (invokers) -> (stack, reference, buffer) -> { + AccessoryNestUtils.recursivelyHandle(stack, reference, (stack1, reference1) -> { + for (var invoker : invokers) { + invoker.canUnequip(stack1, reference1, buffer); + + if(buffer.shouldReturnEarly()) return true; + } + + return null; + }); + } + ); + + /// + /// @param stack The specific stack being evaluated + /// @param reference The reference to the specific location within the Accessories Inventory + /// @param buffer The buffer to send a response to if the Accessory can or can not be unequipped + /// + void canUnequip(ItemStack stack, SlotReference reference, ActionResponseBuffer buffer); +} diff --git a/common/src/main/java/io/wispforest/accessories/api/menu/AccessoriesBasedSlot.java b/common/src/main/java/io/wispforest/accessories/api/menu/AccessoriesBasedSlot.java index e7901dbc7..bb9b2a02c 100644 --- a/common/src/main/java/io/wispforest/accessories/api/menu/AccessoriesBasedSlot.java +++ b/common/src/main/java/io/wispforest/accessories/api/menu/AccessoriesBasedSlot.java @@ -3,34 +3,40 @@ import com.mojang.logging.LogUtils; import io.wispforest.accessories.Accessories; import io.wispforest.accessories.api.AccessoriesContainer; +import io.wispforest.accessories.api.action.ActionResponseBuffer; import io.wispforest.accessories.api.core.AccessoryRegistry; -import io.wispforest.accessories.api.events.AllowEntityModificationCallback; -import io.wispforest.accessories.api.slot.SlotPredicateRegistry; +import io.wispforest.accessories.api.events.v2.AllowEntityModificationCallback; import io.wispforest.accessories.api.slot.SlotReference; import io.wispforest.accessories.api.slot.SlotType; +import io.wispforest.accessories.api.slot.validator.SlotValidatorRegistry; +import io.wispforest.accessories.api.tooltip.TooltipAdder; +import io.wispforest.accessories.api.tooltip.impl.TooltipEntry; +import io.wispforest.accessories.api.tooltip.TooltipInfoProvider; import io.wispforest.accessories.data.EntitySlotLoader; import io.wispforest.accessories.impl.core.ExpandedContainer; import io.wispforest.accessories.menu.SlotTypeAccessible; import io.wispforest.accessories.pond.AccessoriesLivingEntityExtension; import net.minecraft.ChatFormatting; import net.minecraft.network.chat.Component; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.TooltipFlag; import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; -import java.util.ArrayList; import java.util.List; +import java.util.function.Supplier; /** * Base slot class implementation for Accessories with static methods that force checks if * the passed entity and type can be found. Primarily used with internal screen and * with the {@link AccessoriesSlotGenerator} for unique slots API */ -public class AccessoriesBasedSlot extends Slot implements SlotTypeAccessible { +public class AccessoriesBasedSlot extends Slot implements SlotTypeAccessible, TooltipInfoProvider { private static final Logger LOGGER = LogUtils.getLogger(); @@ -38,6 +44,8 @@ public class AccessoriesBasedSlot extends Slot implements SlotTypeAccessible { public final AccessoriesContainer accessoriesContainer; public final boolean isCosmetic; + private Supplier<@Nullable Player> ownerPlayer = () -> null; + public AccessoriesBasedSlot(AccessoriesContainer accessoriesContainer, ExpandedContainer container, int slot, int x, int y) { this(accessoriesContainer, container, accessoriesContainer.getCosmeticAccessories() == container, slot, x, y); } @@ -63,7 +71,7 @@ public static AccessoriesBasedSlot of(LivingEntity livingEntity, SlotType slotTy @Nullable public static AccessoriesBasedSlot of(LivingEntity livingEntity, SlotType slotType, boolean isCosmetic, int slot, int x, int y) { - var capability = livingEntity.accessoriesCapability(); + var capability = ((io.wispforest.accessories.pond.AccessoriesAPIAccess) livingEntity).accessoriesCapability(); if(capability == null) { LOGGER.error("Unable to locate a capability for the given livingEntity meaning it does not have a valid Accessory Inventory [EntityType: {}]", livingEntity.getType()); @@ -90,6 +98,17 @@ public static AccessoriesBasedSlot of(LivingEntity livingEntity, SlotType slotTy return new AccessoriesBasedSlot(container, isCosmetic ? container.getAccessories() : container.getCosmeticAccessories(), slot, x, y); } + public AccessoriesBasedSlot ownerPlayer(Supplier<@Nullable Player> ownerPlayer) { + this.ownerPlayer = ownerPlayer; + + return this; + } + + @Override + public boolean isCosmeticSlot() { + return this.isCosmetic; + } + @Override public AccessoriesContainer getContainer() { return accessoriesContainer; @@ -128,46 +147,75 @@ public void setByPlayer(ItemStack newStack, ItemStack oldStack) { @Override public boolean mayPlace(ItemStack stack) { - // Cosmetic slots do not run the canEquip for the given accessory stack - if (this.isCosmeticSlot()) { - var slotType = this.accessoriesContainer.slotType(); - - return SlotPredicateRegistry.getPredicateResults(slotType.validators(), this.entity.level(), this.entity, slotType, this.getContainerSlot(), stack); - } - - return SlotPredicateRegistry.canInsertIntoSlot(stack, SlotReference.of(this.entity, this.accessoriesContainer.getSlotName(), this.getContainerSlot())); + return canEquipSlotResponse(this.isCosmeticSlot(), ownerPlayer.get(), stack, this.slotReference(), new ActionResponseBuffer(true)) + .canPerformAction() + .isValid(); } @Override public boolean mayPickup(Player player) { - if(!this.entity.equals(player)/*this.entity != player*/) { - var ref = this.accessoriesContainer.createReference(this.getContainerSlot()); - - var result = AllowEntityModificationCallback.EVENT.invoker().allowModifications(this.entity, player, ref); - - if(!result.orElse(false)) return false; - } - - // Cosmetic slots do not run the canUnequip for the given accessory stack - return isCosmetic || AccessoryRegistry.canUnequip(this.getItem(), SlotReference.of(this.entity, this.accessoriesContainer.getSlotName(), this.getContainerSlot())); + return canUnequipSlotResponse(this.isCosmeticSlot(), player, this.getItem(), this.slotReference(), new ActionResponseBuffer(true)) + .canPerformAction() + .isValid(true); } @Override - public ResourceLocation getNoItemIcon(){ + public Identifier getNoItemIcon(){ var slotType = this.accessoriesContainer.slotType(); return slotType != null ? slotType.icon() : SlotType.EMPTY_SLOT_ICON; } + @Deprecated(forRemoval = true) public List getTooltipData() { - var tooltipData = new ArrayList(); + return TooltipInfoProvider.gatherInfo(this, TooltipEntry.of(), Item.TooltipContext.EMPTY, TooltipFlag.NORMAL).entries(); + } + @Override + public void addInfo(TooltipAdder adder, Item.TooltipContext ctx, TooltipFlag type) { var slotType = this.accessoriesContainer.slotType(); - tooltipData.add(Component.translatable(Accessories.translationKey( "slot.tooltip.singular")) - .withStyle(ChatFormatting.GRAY) - .append(Component.translatable(slotType.translation()).withStyle(ChatFormatting.BLUE))); + adder.add( + Component.translatable(Accessories.translationKey( "slot.tooltip.singular")) + .withStyle(ChatFormatting.GRAY) + .append(Component.translatable(slotType.translation()).withStyle(ChatFormatting.BLUE)) + ); + } + + public ActionResponseBuffer checkInsertion(ItemStack stack) { + return canEquipSlotResponse(this.isCosmeticSlot(), ownerPlayer.get(), stack, this.slotReference(), new ActionResponseBuffer(false)); + } + + public ActionResponseBuffer checkExtraction() { + return canUnequipSlotResponse(this.isCosmeticSlot(), ownerPlayer.get(), this.getItem(), this.slotReference(), new ActionResponseBuffer(false)); + } + + public static ActionResponseBuffer canUnequipSlotResponse(boolean isCosmetic, @Nullable Player player, ItemStack stack, SlotReference ref, ActionResponseBuffer buffer){ + var ownerEntity = ref.entity(); + + if (stack.isEmpty()) return buffer; + + if (player != null && !ownerEntity.equals(player)) AllowEntityModificationCallback.EVENT.invoker().allowModifications(ownerEntity, player, ref, buffer); + if (!buffer.shouldReturnEarly() && !isCosmetic) AccessoryRegistry.canUnequipResponse(stack, ref, buffer); + + return buffer; + } + + public static ActionResponseBuffer canEquipSlotResponse(boolean isCosmetic, @Nullable Player player, ItemStack stack, SlotReference ref, ActionResponseBuffer buffer){ + var ownerEntity = ref.entity(); + + if (stack.isEmpty()) return buffer; + + if (player != null && !ownerEntity.equals(player)) AllowEntityModificationCallback.EVENT.invoker().allowModifications(ownerEntity, player, ref, buffer); + if (!buffer.shouldReturnEarly()) { + if (isCosmetic) { + var type = ref.type(); + SlotValidatorRegistry.getPredicateResponse(type.validators(), ownerEntity.level(), ownerEntity, type, ref.index(), stack, buffer); + } else { + SlotValidatorRegistry.canInsertIntoSlotResponse(stack, ref, buffer); + } + } - return tooltipData; + return buffer; } } diff --git a/common/src/main/java/io/wispforest/accessories/api/menu/AccessoriesSlotGenerator.java b/common/src/main/java/io/wispforest/accessories/api/menu/AccessoriesSlotGenerator.java index 5fb67a014..1302bba02 100644 --- a/common/src/main/java/io/wispforest/accessories/api/menu/AccessoriesSlotGenerator.java +++ b/common/src/main/java/io/wispforest/accessories/api/menu/AccessoriesSlotGenerator.java @@ -7,6 +7,7 @@ import io.wispforest.accessories.api.slot.UniqueSlotHandling; import io.wispforest.accessories.data.EntitySlotLoader; import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.Slot; import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; @@ -16,6 +17,7 @@ import java.util.List; import java.util.Objects; import java.util.function.Consumer; +import java.util.function.Supplier; /** * Slot Generator to be used for slots generator from {@link UniqueSlotHandling} event hooks @@ -29,6 +31,8 @@ public class AccessoriesSlotGenerator { private final Consumer slotConsumer; + private Supplier<@Nullable Player> ownerPlayer = () -> null; + private List slotTypes = List.of(); private int horizontalPadding = 0, verticalPadding = 0; @@ -45,7 +49,7 @@ private AccessoriesSlotGenerator(Consumer slotConsumer, int startX, int st @Nullable public static AccessoriesSlotGenerator of(Consumer slotConsumer, int startX, int startY, LivingEntity livingEntity, SlotTypeReference... references) { - var capability = livingEntity.accessoriesCapability(); + var capability = ((io.wispforest.accessories.pond.AccessoriesAPIAccess) livingEntity).accessoriesCapability(); if(capability == null) return null; @@ -54,7 +58,7 @@ public static AccessoriesSlotGenerator of(Consumer slotConsumer, int start @Nullable public static AccessoriesSlotGenerator of(Consumer slotConsumer, int startX, int startY, LivingEntity livingEntity, SlotType... slotTypes) { - var capability = livingEntity.accessoriesCapability(); + var capability = ((io.wispforest.accessories.pond.AccessoriesAPIAccess) livingEntity).accessoriesCapability(); if(capability == null) return null; @@ -68,13 +72,19 @@ public static AccessoriesSlotGenerator of(Consumer slotConsumer, int start */ @Nullable public static AccessoriesSlotGenerator of(Consumer slotConsumer, int startX, int startY, LivingEntity livingEntity) { - var capability = livingEntity.accessoriesCapability(); + var capability = ((io.wispforest.accessories.pond.AccessoriesAPIAccess) livingEntity).accessoriesCapability(); if(capability == null) return null; return new AccessoriesSlotGenerator(slotConsumer, startX, startY, capability); } + public AccessoriesSlotGenerator ownerPlayer(Supplier<@Nullable Player> ownerPlayer) { + this.ownerPlayer = ownerPlayer; + + return this; + } + /** * Adjust the given padding of the generator for all sides of a generated slot */ @@ -204,7 +214,7 @@ private int layoutSlots(LayoutType type) { for (var container : containers) { for (int i = 0; i < container.getSize(); i++) { - slotConsumer.accept(new AccessoriesBasedSlot(container, container.getAccessories(), i, this.startX + xOffset, this.startY + yOffset)); + slotConsumer.accept(new AccessoriesBasedSlot(container, container.getAccessories(), i, this.startX + xOffset, this.startY + yOffset).ownerPlayer(ownerPlayer)); if(type == LayoutType.COLUMN) { yOffset += (this.verticalPadding) + 18; diff --git a/common/src/main/java/io/wispforest/accessories/api/slot/EntityBasedPredicate.java b/common/src/main/java/io/wispforest/accessories/api/slot/EntityBasedPredicate.java index acc074c61..0c635f539 100644 --- a/common/src/main/java/io/wispforest/accessories/api/slot/EntityBasedPredicate.java +++ b/common/src/main/java/io/wispforest/accessories/api/slot/EntityBasedPredicate.java @@ -1,6 +1,10 @@ package io.wispforest.accessories.api.slot; +import io.wispforest.accessories.api.action.ActionResponse; +import io.wispforest.accessories.api.action.ActionResponseBuffer; +import io.wispforest.accessories.api.slot.validator.EntitySlotValidator; import net.fabricmc.fabric.api.util.TriState; +import net.minecraft.network.chat.Component; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; @@ -9,7 +13,8 @@ /** * Similar to {@link SlotBasedPredicate} but allows for {@link LivingEntity} if such is required */ -public interface EntityBasedPredicate extends SlotBasedPredicate { +@Deprecated(forRemoval = true) +public interface EntityBasedPredicate extends SlotBasedPredicate, EntitySlotValidator { TriState isValid(Level level, @Nullable LivingEntity entity, SlotType slotType, int index, ItemStack stack); @@ -17,4 +22,22 @@ public interface EntityBasedPredicate extends SlotBasedPredicate { default TriState isValid(Level level, SlotType slotType, int slot, ItemStack stack) { return isValid(level, null, slotType, slot, stack); } + + @Override + default void isValidForSlot(Level level, SlotType slotType, int index, ItemStack stack, ActionResponseBuffer buffer) { + SlotBasedPredicate.super.isValidForSlot(level, slotType, index, stack, buffer); + } + + @Override + default void isValidForSlot(@Nullable LivingEntity entity, Level level, SlotType slotType, int index, ItemStack stack, ActionResponseBuffer buffer) { + var isValid = isValid(level, entity, slotType, index, stack); + + if (isValid == TriState.DEFAULT) return; + + var message = isValid.get() + ? Component.literal("Such an item is valid to be equipped!") + : Component.literal("Such an item is not valid to be equipped!"); + + buffer.respondWith(ActionResponse.of(isValid.get(), message)); + } } diff --git a/common/src/main/java/io/wispforest/accessories/api/slot/SlotBasedPredicate.java b/common/src/main/java/io/wispforest/accessories/api/slot/SlotBasedPredicate.java index 2fe188eba..d98738cb8 100644 --- a/common/src/main/java/io/wispforest/accessories/api/slot/SlotBasedPredicate.java +++ b/common/src/main/java/io/wispforest/accessories/api/slot/SlotBasedPredicate.java @@ -1,6 +1,10 @@ package io.wispforest.accessories.api.slot; +import io.wispforest.accessories.api.action.ActionResponse; +import io.wispforest.accessories.api.action.ActionResponseBuffer; +import io.wispforest.accessories.api.slot.validator.SlotValidator; import net.fabricmc.fabric.api.util.TriState; +import net.minecraft.network.chat.Component; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; @@ -10,7 +14,8 @@ /** * Predicate used to verify if the given stack is valid for the passed SlotType and index */ -public interface SlotBasedPredicate { +@Deprecated(forRemoval = true) +public interface SlotBasedPredicate extends SlotValidator { /** * Predicate method used to check if the given stack is valid for the given slot @@ -40,4 +45,19 @@ static SlotBasedPredicate ofClass(Class clazz) { static SlotBasedPredicate withEntity(EntityBasedPredicate entityBasedPredicate) { return entityBasedPredicate; } + + //-- + + @Override + default void isValidForSlot(Level level, SlotType slotType, int index, ItemStack stack, ActionResponseBuffer buffer) { + var isValid = isValid(level, slotType, index, stack); + + if (isValid == TriState.DEFAULT) return; + + var message = isValid.get() + ? Component.literal("Such an item is valid to be equipped!") + : Component.literal("Such an item is not valid to be equipped!"); + + buffer.respondWith(ActionResponse.of(isValid.get(), message)); + } } diff --git a/common/src/main/java/io/wispforest/accessories/api/slot/SlotGroup.java b/common/src/main/java/io/wispforest/accessories/api/slot/SlotGroup.java index 83bee49d4..071488242 100644 --- a/common/src/main/java/io/wispforest/accessories/api/slot/SlotGroup.java +++ b/common/src/main/java/io/wispforest/accessories/api/slot/SlotGroup.java @@ -3,7 +3,7 @@ import io.wispforest.accessories.Accessories; import io.wispforest.accessories.data.SlotGroupLoader; import net.minecraft.network.chat.Component; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import org.jetbrains.annotations.NotNull; import java.util.Set; @@ -17,7 +17,7 @@ /// public interface SlotGroup extends Comparable { - ResourceLocation UNKNOWN = Accessories.of("gui/group/unknown"); + Identifier UNKNOWN = Accessories.of("gui/group/unknown"); /// /// @return The group name which may or may not contain a namespace @@ -27,7 +27,7 @@ public interface SlotGroup extends Comparable { /// /// @return A parsed group name as either `accessories:{group_name_here}` or `{group_namespace_here}:{group_name_here}` /// - default ResourceLocation getId() { + default Identifier getId() { return Accessories.parseLocationOrDefault(this.name()); } @@ -41,7 +41,7 @@ default String translation(){ /// /// @return The location for the given icon within the GUI Atlas for the given slot group /// - ResourceLocation icon(); + Identifier icon(); /// /// Used with sorting all registered groups when creating list of slot groups diff --git a/common/src/main/java/io/wispforest/accessories/api/slot/SlotPath.java b/common/src/main/java/io/wispforest/accessories/api/slot/SlotPath.java index c18ebb35f..1d3cc93e0 100644 --- a/common/src/main/java/io/wispforest/accessories/api/slot/SlotPath.java +++ b/common/src/main/java/io/wispforest/accessories/api/slot/SlotPath.java @@ -11,7 +11,7 @@ import io.wispforest.owo.serialization.CodecUtils; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.codec.StreamCodec; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.world.item.ItemStack; import org.apache.commons.lang3.RegExUtils; import org.jetbrains.annotations.ApiStatus; @@ -159,15 +159,15 @@ default String createString() { : location.toString().replace(":", "-"); } - default ResourceLocation toLocation() { + default Identifier toLocation() { var parts = slotName().split(":"); - ResourceLocation location; + Identifier location; if (parts.length == 1) { location = Accessories.of(parts[0]); } else { - location = ResourceLocation.fromNamespaceAndPath(parts[0], slotName().replace(parts[0] + ":", "")); + location = Identifier.fromNamespaceAndPath(parts[0], slotName().replace(parts[0] + ":", "")); } location = location.withSuffix("/" + index()); diff --git a/common/src/main/java/io/wispforest/accessories/api/slot/SlotPredicateRegistry.java b/common/src/main/java/io/wispforest/accessories/api/slot/SlotPredicateRegistry.java index 4fff2857b..3d00d860b 100644 --- a/common/src/main/java/io/wispforest/accessories/api/slot/SlotPredicateRegistry.java +++ b/common/src/main/java/io/wispforest/accessories/api/slot/SlotPredicateRegistry.java @@ -1,51 +1,61 @@ package io.wispforest.accessories.api.slot; -import com.mojang.logging.LogUtils; -import io.wispforest.accessories.Accessories; -import io.wispforest.accessories.api.AccessoriesCapability; -import io.wispforest.accessories.api.components.AccessoriesDataComponents; +import io.wispforest.accessories.api.action.ActionResponseBuffer; import io.wispforest.accessories.api.core.Accessory; -import io.wispforest.accessories.api.core.AccessoryRegistry; -import io.wispforest.accessories.api.data.AccessoriesBaseData; -import io.wispforest.accessories.api.data.AccessoriesTags; -import io.wispforest.accessories.data.EntitySlotLoader; -import io.wispforest.accessories.data.SlotTypeLoader; -import io.wispforest.accessories.impl.AccessoryAttributeLogic; +import io.wispforest.accessories.api.slot.validator.EntitySlotValidator; +import io.wispforest.accessories.api.slot.validator.SlotValidator; +import io.wispforest.accessories.api.slot.validator.SlotValidatorRegistry; import net.fabricmc.fabric.api.util.TriState; -import net.minecraft.core.registries.Registries; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.tags.TagKey; +import net.minecraft.resources.Identifier; import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import org.jetbrains.annotations.Nullable; -import org.slf4j.Logger; import java.util.*; +@Deprecated(forRemoval = true) public class SlotPredicateRegistry { - private static final Logger LOGGER = LogUtils.getLogger(); + public static void register(Identifier location, SlotBasedPredicate predicate) { + SlotValidatorRegistry.register(location, predicate); + } - private static final Map PREDICATES = new HashMap<>(); + /** + * @return {@link SlotBasedPredicate} bound to the given {@link Identifier} or an Empty {@link Optional} if absent + */ + @Nullable + public static SlotBasedPredicate getPredicate(Identifier location) { + var validator = SlotValidatorRegistry.getPredicate(location); - public static void register(ResourceLocation location, SlotBasedPredicate predicate) { - if(PREDICATES.containsKey(location)) { - LOGGER.warn("[AccessoriesAPI]: A SlotBasedPredicate attempted to be registered but a duplicate entry existed already! [Id: {}]", location); + if (validator == null) return null; + if (validator instanceof SlotBasedPredicate predicate) return predicate; - return; - } + return (validator instanceof EntitySlotValidator entityValidator) + ? new EntitySlotPredicateWrapper(entityValidator) + : new SlotPredicateWrapper(validator); + } + + private record SlotPredicateWrapper(SlotValidator validator) implements SlotBasedPredicate { + @Override + public TriState isValid(Level level, SlotType slotType, int index, ItemStack stack) { + var buffer = new ActionResponseBuffer(true); - PREDICATES.put(location, predicate); + validator.isValidForSlot(level, slotType, index, stack, buffer); + + return buffer.canPerformAction().toTriState(); + } } - /** - * @return {@link SlotBasedPredicate} bound to the given {@link ResourceLocation} or an Empty {@link Optional} if absent - */ - @Nullable - public static SlotBasedPredicate getPredicate(ResourceLocation location) { - return PREDICATES.get(location); + private record EntitySlotPredicateWrapper(EntitySlotValidator validator) implements EntityBasedPredicate { + @Override + public TriState isValid(Level level, @Nullable LivingEntity entity, SlotType slotType, int index, ItemStack stack) { + var buffer = new ActionResponseBuffer(true); + + validator.isValidForSlot(entity, level, slotType, index, stack, buffer); + + return buffer.canPerformAction().toTriState(); + } } //-- @@ -55,13 +65,7 @@ public static SlotBasedPredicate getPredicate(ResourceLocation location) { * based on {@link SlotBasedPredicate}s bound to the Slot and the {@link Accessory} bound to the stack if present */ public static boolean canInsertIntoSlot(ItemStack stack, SlotReference reference){ - var slotType = reference.type(); - - if(slotType == null) { - throw new IllegalStateException("Unable to get the needed SlotType from the SlotReference passed within `canInsertIntoSlot`! [Name: " + reference.slotName() + "]"); - } - - return getPredicateResults(slotType.validators(), reference.entity().level(), reference.entity(), slotType, 0, stack) && AccessoryRegistry.canEquip(stack, reference); + return SlotValidatorRegistry.canInsertIntoSlot(stack, reference); } /** @@ -69,37 +73,7 @@ public static boolean canInsertIntoSlot(ItemStack stack, SlotReference reference * available {@link SlotType}s */ public static Collection getValidSlotTypes(LivingEntity entity, ItemStack stack){ - var slots = EntitySlotLoader.getEntitySlots(entity); - - var validSlots = new ArrayList(); - - var capability = AccessoriesCapability.get(entity); - - if(capability != null) { - var containers = capability.getContainers(); - - for (SlotType value : slots.values()) { - if (!containers.containsKey(value.name())) continue; - - var container = containers.get(value.name()); - - var size = containers.get(value.name()).getSize(); - - if(size == 0) size = 1; - - for (int i = 0; i < size; i++) { - var reference = SlotReference.of(entity, container.getSlotName(), i); - - if (canInsertIntoSlot(stack, reference)) { - validSlots.add(value); - - break; - } - } - } - } - - return validSlots; + return SlotValidatorRegistry.getValidSlotTypes(entity, stack); } public static boolean isValidAccessory(ItemStack stack, Level level){ @@ -111,8 +85,7 @@ public static boolean isValidAccessory(ItemStack stack, Level level){ * default or if the given stack has valid slots which it can be equipped */ public static boolean isValidAccessory(ItemStack stack, Level level, @Nullable LivingEntity entity){ - return !AccessoryRegistry.isDefaultAccessory(AccessoryRegistry.getAccessoryOrDefault(stack)) - || !getStackSlotTypes(level, entity, stack).isEmpty(); + return SlotValidatorRegistry.isValidAccessory(stack, level, entity); } public static Collection getStackSlotTypes(Level level, ItemStack stack){ @@ -124,82 +97,14 @@ public static Collection getStackSlotTypes(LivingEntity entity, ItemSt } public static Collection getStackSlotTypes(Level level, @Nullable LivingEntity entity, ItemStack stack) { - var validSlots = new ArrayList(); - - for (SlotType value : SlotTypeLoader.INSTANCE.getEntries(level).values()) { - if(getPredicateResults(value.validators(), level, entity, value, 0, stack)) validSlots.add(value); - } - - return validSlots; + return SlotValidatorRegistry.getStackSlotTypes(level, entity, stack); } - public static boolean getPredicateResults(Set predicateIds, Level level, SlotType slotType, int index, ItemStack stack){ + public static boolean getPredicateResults(Set predicateIds, Level level, SlotType slotType, int index, ItemStack stack){ return getPredicateResults(predicateIds, level, null, slotType, index, stack); } - public static boolean getPredicateResults(Set predicateIds, Level level, @Nullable LivingEntity entity, SlotType slotType, int index, ItemStack stack){ - var result = TriState.DEFAULT; - - for (var predicateId : predicateIds) { - var predicate = getPredicate(predicateId); - - if(predicate == null) continue; - - if(predicate instanceof EntityBasedPredicate entityBasedPredicate) { - result = entityBasedPredicate.isValid(level, entity, slotType, index, stack); - } else { - result = predicate.isValid(level, slotType, index, stack); - } - - if(result != TriState.DEFAULT) break; - } - - return result.orElse(false); - } - - private static TagKey getSlotTag(SlotType slotType) { - var location = UniqueSlotHandling.isUniqueSlot(slotType.name()) ? ResourceLocation.parse(slotType.name()) : Accessories.of(slotType.name()); - - return TagKey.create(Registries.ITEM, location); - } - - static { - register(AccessoriesBaseData.ALL_PREDICATE_ID, (level, slotType, i, stack) -> TriState.TRUE); - register(AccessoriesBaseData.NONE_PREDICATE_ID, (level, slotType, i, stack) -> TriState.FALSE); - register(AccessoriesBaseData.TAG_PREDICATE_ID, (level, slotType, i, stack) -> { - return (stack.is(getSlotTag(slotType)) || stack.is(AccessoriesTags.ANY_TAG)) ? TriState.TRUE : TriState.DEFAULT; - }); - register(AccessoriesBaseData.ATTRIBUTE_PREDICATE_ID, SlotBasedPredicate.withEntity((level, entity, slotType, index, stack) -> { - var bl = !AccessoryAttributeLogic.getAttributeModifiers(stack, entity, slotType.name(), index) - .getAttributeModifiers(false, true).isEmpty(); - - return bl ? TriState.TRUE : TriState.DEFAULT; - })); - register(AccessoriesBaseData.COMPONENT_PREDICATE_ID, (level, slotType, index, stack) -> { - if(stack.has(AccessoriesDataComponents.SLOT_VALIDATION)) { - var slotValidationData = stack.get(AccessoriesDataComponents.SLOT_VALIDATION); - var name = slotType.name(); - - //-- - - var invalidSlots = slotValidationData.invalidSlotOverrides(); - - for (var invalidSlot : invalidSlots) { - if (name.equals(invalidSlot)) return TriState.FALSE; - } - - //-- - - var validSlots = slotValidationData.validSlotOverrides(); - - for (var validSlot : validSlots) { - if (validSlot.equals("any")) return TriState.TRUE; - - if (name.equals(validSlot)) return TriState.TRUE; - } - } - - return TriState.DEFAULT; - }); + public static boolean getPredicateResults(Set predicateIds, Level level, @Nullable LivingEntity entity, SlotType slotType, int index, ItemStack stack){ + return SlotValidatorRegistry.getPredicateResults(predicateIds, level, entity, slotType, index, stack); } } diff --git a/common/src/main/java/io/wispforest/accessories/api/slot/SlotReference.java b/common/src/main/java/io/wispforest/accessories/api/slot/SlotReference.java index 8c2e5a50f..11b8bfd0b 100644 --- a/common/src/main/java/io/wispforest/accessories/api/slot/SlotReference.java +++ b/common/src/main/java/io/wispforest/accessories/api/slot/SlotReference.java @@ -94,7 +94,7 @@ default SlotType type(){ /// @Nullable default AccessoriesCapability capability() { - return this.entity().accessoriesCapability(); + return ((io.wispforest.accessories.pond.AccessoriesAPIAccess) this.entity()).accessoriesCapability(); } /// diff --git a/common/src/main/java/io/wispforest/accessories/api/slot/SlotType.java b/common/src/main/java/io/wispforest/accessories/api/slot/SlotType.java index 761cdb163..5d5a1d775 100644 --- a/common/src/main/java/io/wispforest/accessories/api/slot/SlotType.java +++ b/common/src/main/java/io/wispforest/accessories/api/slot/SlotType.java @@ -3,9 +3,10 @@ import io.wispforest.accessories.Accessories; import io.wispforest.accessories.api.AccessoriesStorage; import io.wispforest.accessories.api.events.DropRule; +import io.wispforest.accessories.api.slot.validator.SlotValidatorRegistry; import io.wispforest.accessories.data.SlotTypeLoader; import net.minecraft.network.chat.Component; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import org.jetbrains.annotations.NotNull; import java.util.Set; @@ -18,7 +19,7 @@ /// public interface SlotType extends Comparable { - ResourceLocation EMPTY_SLOT_ICON = Accessories.of("gui/slot/empty"); + Identifier EMPTY_SLOT_ICON = Accessories.of("gui/slot/empty"); /// /// @return The slot name which may or may not contain a namespace @@ -28,7 +29,7 @@ public interface SlotType extends Comparable { /// /// @return A parsed slot name as either `accessories:{group_name_here}` or `{group_namespace_here}:{group_name_here}` /// - default ResourceLocation getId() { + default Identifier getId() { return Accessories.parseLocationOrDefault(this.name()); } @@ -36,13 +37,17 @@ default ResourceLocation getId() { /// @return A {@link Component} Translation key for the given slot /// default String translation(){ - return Accessories.translationKey("slot." + name().replace(":", ".")); + return toTranslationKey(name()); + } + + static String toTranslationKey(String slotName){ + return Accessories.translationKey("slot." + slotName.replace(":", ".")); } /// /// @return The location for the given icon within the Block Atlas for the given slot type. /// - ResourceLocation icon(); + Identifier icon(); /// /// Used with sorting all registered slots within a given group when creating list of slots @@ -57,10 +62,10 @@ default String translation(){ int amount(); /// - /// @return A set of [ResourceLocation] used to check if an accessory is valid for the given - /// slot used within {@link SlotPredicateRegistry#canInsertIntoSlot}. + /// @return A set of [Identifier] used to check if an accessory is valid for the given + /// slot used within {@link SlotValidatorRegistry#canInsertIntoSlot}. /// - Set validators(); + Set validators(); /// /// @return The given {@link DropRule} used upon an entity's death to decided what action to perform with diff --git a/common/src/main/java/io/wispforest/accessories/api/slot/UniqueSlotHandling.java b/common/src/main/java/io/wispforest/accessories/api/slot/UniqueSlotHandling.java index 88d59f132..14e09671e 100644 --- a/common/src/main/java/io/wispforest/accessories/api/slot/UniqueSlotHandling.java +++ b/common/src/main/java/io/wispforest/accessories/api/slot/UniqueSlotHandling.java @@ -11,7 +11,7 @@ import net.fabricmc.fabric.api.event.EventFactory; import net.minecraft.core.RegistrySetBuilder; import net.minecraft.resources.ResourceKey; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.world.entity.EntityType; import net.minecraft.world.item.ItemStack; import org.apache.commons.lang3.function.TriFunction; @@ -56,7 +56,7 @@ public interface UniqueSlotBuilderFactory { /** * Starts building a new unique slot. */ - UniqueSlotBuilder create(ResourceLocation location, int amount); + UniqueSlotBuilder create(Identifier location, int amount); } /** @@ -69,7 +69,7 @@ public interface UniqueSlotBuilder { *

* By default, the tag-based slot predicate is used. */ - UniqueSlotBuilder slotPredicates(ResourceLocation... locations); + UniqueSlotBuilder slotPredicates(Identifier... locations); /** * Sets the list of entity types that will have this slot. @@ -118,7 +118,7 @@ public static void bootStrapDataGen(RegistrySetBuilder registryBuilder) { //-- @ApiStatus.Internal - public static void gatherUniqueSlots(TriFunction, SlotTypeReference> slotRegistration) { + public static void gatherUniqueSlots(TriFunction, SlotTypeReference> slotRegistration) { GROUPS_SERVER.clear(); SLOT_TO_ENTITIES.clear(); @@ -130,7 +130,7 @@ public static void gatherUniqueSlots(TriFunction new UniqueSlotBuilder() { - @Override public UniqueSlotBuilder slotPredicates(ResourceLocation... locations) { return this; } + @Override public UniqueSlotBuilder slotPredicates(Identifier... locations) { return this; } @Override public UniqueSlotBuilder validTypes(EntityType... types) { return this; } @Override public UniqueSlotBuilder strictMode(StrictMode value) { return this; } @Override public UniqueSlotBuilder allowResizing(boolean value) { return this; } @@ -155,9 +155,9 @@ public SlotTypeReference build() { } private static final class ServerUniqueSlotBuilder implements UniqueSlotBuilder { - private final ResourceLocation location; + private final Identifier location; private final int amount; - private Set slotPredicates = Set.of(Accessories.of("tag")); + private Set slotPredicates = Set.of(Accessories.of("tag")); private Set> validTypes = Set.of(); private StrictMode mode = StrictMode.FULL; @@ -165,9 +165,9 @@ private static final class ServerUniqueSlotBuilder implements UniqueSlotBuilder private boolean allowEquipFromUse = true; private boolean allowTooltipInfo = true; - private final TriFunction, SlotTypeReference> slotRegistration; + private final TriFunction, SlotTypeReference> slotRegistration; - ServerUniqueSlotBuilder(ResourceLocation location, int amount, TriFunction, SlotTypeReference> slotRegistration){ + ServerUniqueSlotBuilder(Identifier location, int amount, TriFunction, SlotTypeReference> slotRegistration){ this.location = location; this.amount = amount; @@ -175,7 +175,7 @@ private static final class ServerUniqueSlotBuilder implements UniqueSlotBuilder } @Override - public ServerUniqueSlotBuilder slotPredicates(ResourceLocation... locations) { + public ServerUniqueSlotBuilder slotPredicates(Identifier... locations) { this.slotPredicates = Set.of(locations); return this; diff --git a/common/src/main/java/io/wispforest/accessories/api/slot/validator/EntitySlotValidator.java b/common/src/main/java/io/wispforest/accessories/api/slot/validator/EntitySlotValidator.java new file mode 100644 index 000000000..bd7b715f3 --- /dev/null +++ b/common/src/main/java/io/wispforest/accessories/api/slot/validator/EntitySlotValidator.java @@ -0,0 +1,22 @@ +package io.wispforest.accessories.api.slot.validator; + +import io.wispforest.accessories.api.action.ActionResponseBuffer; +import io.wispforest.accessories.api.slot.SlotType; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import org.jetbrains.annotations.Nullable; + +public interface EntitySlotValidator extends SlotValidator { + + void isValidForSlot(@Nullable LivingEntity entity, Level level, SlotType slotType, int index, ItemStack stack, ActionResponseBuffer buffer); + + @Override + default void isValidForSlot(Level level, SlotType slotType, int index, ItemStack stack, ActionResponseBuffer buffer) { + try { + isValidForSlot(level, slotType, index, stack, buffer); + } catch (Exception e) { + throw new IllegalStateException("Caught an Exception when calling isValidForSlot() for a EntitySlotValidator possible due to improper handling of null entity!", e); + } + } +} diff --git a/common/src/main/java/io/wispforest/accessories/api/slot/validator/SlotValidator.java b/common/src/main/java/io/wispforest/accessories/api/slot/validator/SlotValidator.java new file mode 100644 index 000000000..ca37783ec --- /dev/null +++ b/common/src/main/java/io/wispforest/accessories/api/slot/validator/SlotValidator.java @@ -0,0 +1,58 @@ +package io.wispforest.accessories.api.slot.validator; + +import io.wispforest.accessories.api.action.ActionResponse; +import io.wispforest.accessories.api.action.ActionResponseBuffer; +import io.wispforest.accessories.api.slot.SlotType; +import net.minecraft.network.chat.Component; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; + +import java.util.function.Predicate; + +public interface SlotValidator { + + void isValidForSlot(Level level, SlotType slotType, int index, ItemStack stack, ActionResponseBuffer buffer); + + static SlotValidator ofItem(Predicate predicate) { + return ofItem(predicate, SlotValidatorReasons.INVALID_ITEM); + } + + /** + * @return Predicate that checks solely using the passed stacks item + */ + static SlotValidator ofItem(Predicate predicate, Component invalidReason) { + return (level, slotType, index, stack, buffer) -> { + var isSuccess = predicate.test(stack.getItem()); + + if (!isSuccess) { + buffer.respondWith(ActionResponse.of(false, invalidReason)); + } else { + buffer.respondWith(ActionResponse.SUCCESS); + } + }; + } + + static SlotValidator ofClass(Class clazz) { + return ofClass(clazz, SlotValidatorReasons.INVALID_ITEM); + } + + /** + * @return Predicate that checks if the passed {@link Item} from the stack is instance of the given {@link Class} + */ + static SlotValidator ofClass(Class clazz, Component invalidReason) { + return (level, slotType, index, stack, buffer) -> { + var isSuccess = clazz.isInstance(stack.getItem()); + + if (!isSuccess) { + buffer.respondWith(ActionResponse.of(false, invalidReason)); + } else { + buffer.respondWith(ActionResponse.SUCCESS); + } + }; + } + + static SlotValidator withEntity(EntitySlotValidator entitySlotValidator) { + return entitySlotValidator; + } +} diff --git a/common/src/main/java/io/wispforest/accessories/api/slot/validator/SlotValidatorReasons.java b/common/src/main/java/io/wispforest/accessories/api/slot/validator/SlotValidatorReasons.java new file mode 100644 index 000000000..a526a9997 --- /dev/null +++ b/common/src/main/java/io/wispforest/accessories/api/slot/validator/SlotValidatorReasons.java @@ -0,0 +1,12 @@ +package io.wispforest.accessories.api.slot.validator; + +import io.wispforest.accessories.Accessories; +import io.wispforest.accessories.api.action.ActionResponse; +import net.minecraft.network.chat.Component; + +public class SlotValidatorReasons { + public static final Component INVALID_ITEM = Component.literal("The given Item is not allowed within the slot"); + + static final ActionResponse ALWAYS_VALID = ActionResponse.of(false, Accessories.translation("tooltip.validator.always_valid")); + static final ActionResponse ALWAYS_INVALID = ActionResponse.of(false, Accessories.translation("tooltip.validator.always_invalid")); +} diff --git a/common/src/main/java/io/wispforest/accessories/api/slot/validator/SlotValidatorRegistry.java b/common/src/main/java/io/wispforest/accessories/api/slot/validator/SlotValidatorRegistry.java new file mode 100644 index 000000000..aff4f8807 --- /dev/null +++ b/common/src/main/java/io/wispforest/accessories/api/slot/validator/SlotValidatorRegistry.java @@ -0,0 +1,218 @@ +package io.wispforest.accessories.api.slot.validator; + +import com.mojang.logging.LogUtils; +import io.wispforest.accessories.Accessories; +import io.wispforest.accessories.api.AccessoriesCapability; +import io.wispforest.accessories.api.action.*; +import io.wispforest.accessories.api.components.AccessoriesDataComponents; +import io.wispforest.accessories.api.components.AccessorySlotValidationComponent; +import io.wispforest.accessories.api.core.Accessory; +import io.wispforest.accessories.api.core.AccessoryRegistry; +import io.wispforest.accessories.api.data.AccessoriesBaseData; +import io.wispforest.accessories.api.data.AccessoriesTags; +import io.wispforest.accessories.api.slot.*; +import io.wispforest.accessories.data.EntitySlotLoader; +import io.wispforest.accessories.data.SlotTypeLoader; +import io.wispforest.accessories.impl.AccessoryAttributeLogic; +import net.minecraft.core.registries.Registries; +import net.minecraft.resources.Identifier; +import net.minecraft.tags.TagKey; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import org.jetbrains.annotations.Nullable; +import org.slf4j.Logger; + +import java.util.*; + +public class SlotValidatorRegistry { + + private static final Logger LOGGER = LogUtils.getLogger(); + + private static final Map PREDICATES = new HashMap<>(); + + public static void register(Identifier location, SlotValidator predicate) { + if(PREDICATES.containsKey(location)) { + LOGGER.warn("[AccessoriesAPI]: A SlotValidator attempted to be registered but a duplicate entry existed already! [Id: {}]", location); + + return; + } + + PREDICATES.put(location, predicate); + } + + /** + * @return {@link SlotValidator} bound to the given {@link Identifier} or an Empty {@link Optional} if absent + */ + @Nullable + public static SlotValidator getPredicate(Identifier location) { + return PREDICATES.get(location); + } + + //-- + + /** + * Used to check if the given {@link ItemStack} is valid for the given LivingEntity and SlotReference + * based on {@link SlotValidator}s bound to the Slot and the {@link Accessory} bound to the stack if present + */ + public static boolean canInsertIntoSlot(ItemStack stack, SlotReference reference){ + var slotType = reference.type(); + + if(slotType == null) { + throw new IllegalStateException("Unable to get the needed SlotType from the SlotReference passed within `canInsertIntoSlot`! [Name: " + reference.slotName() + "]"); + } + + return getPredicateResults(slotType.validators(), reference.entity().level(), reference.entity(), slotType, 0, stack) && AccessoryRegistry.canEquip(stack, reference); + } + + public static ActionResponseBuffer canInsertIntoSlotResponse(ItemStack stack, SlotReference reference, ActionResponseBuffer buffer){ + var slotType = reference.type(); + + if(slotType == null) { + throw new IllegalStateException("Unable to get the needed SlotType from the SlotReference passed within `canInsertIntoSlot`! [Name: " + reference.slotName() + "]"); + } + + getPredicateResponse(slotType.validators(), reference.entity().level(), reference.entity(), slotType, 0, stack, buffer); + + AccessoryRegistry.canEquipResponse(stack, reference, buffer); + + return buffer; + } + + /** + * @return All valid {@link SlotType}s for the given {@link ItemStack} based on the {@link LivingEntity} + * available {@link SlotType}s + */ + public static Collection getValidSlotTypes(LivingEntity entity, ItemStack stack){ + var slots = EntitySlotLoader.getEntitySlots(entity); + + var validSlots = new ArrayList(); + + var capability = AccessoriesCapability.get(entity); + + if(capability != null) { + var containers = capability.getContainers(); + + for (SlotType value : slots.values()) { + if (!containers.containsKey(value.name())) continue; + + var container = containers.get(value.name()); + + var size = containers.get(value.name()).getSize(); + + if(size == 0) size = 1; + + for (int i = 0; i < size; i++) { + var reference = SlotReference.of(entity, container.getSlotName(), i); + + if (canInsertIntoSlot(stack, reference)) { + validSlots.add(value); + + break; + } + } + } + } + + return validSlots; + } + + public static boolean isValidAccessory(ItemStack stack, Level level){ + return isValidAccessory(stack, level, null); + } + + /** + * @return If a given {@link ItemStack} is found either to have an {@link Accessory} besides the + * default or if the given stack has valid slots which it can be equipped + */ + public static boolean isValidAccessory(ItemStack stack, Level level, @Nullable LivingEntity entity){ + return !AccessoryRegistry.isDefaultAccessory(AccessoryRegistry.getAccessoryOrDefault(stack)) + || !getStackSlotTypes(level, entity, stack).isEmpty(); + } + + public static Collection getStackSlotTypes(Level level, ItemStack stack){ + return getStackSlotTypes(level, null, stack); + } + + public static Collection getStackSlotTypes(LivingEntity entity, ItemStack stack) { + return getStackSlotTypes(entity.level(), entity, stack); + } + + public static Collection getStackSlotTypes(Level level, @Nullable LivingEntity entity, ItemStack stack) { + var validSlots = new ArrayList(); + + for (SlotType value : SlotTypeLoader.INSTANCE.getEntries(level).values()) { + if(getPredicateResults(value.validators(), level, entity, value, 0, stack)) validSlots.add(value); + } + + return validSlots; + } + + public static boolean getPredicateResults(Set predicateIds, Level level, SlotType slotType, int index, ItemStack stack){ + return getPredicateResults(predicateIds, level, null, slotType, index, stack); + } + + public static boolean getPredicateResults(Set predicateIds, Level level, @Nullable LivingEntity entity, SlotType slotType, int index, ItemStack stack){ + return getPredicateResponse(predicateIds, level, entity, slotType, index, stack, new ActionResponseBuffer(true)) + .canPerformAction() + .isValid(false); + } + + public static ActionResponseBuffer getPredicateResponse(Set predicateIds, Level level, @Nullable LivingEntity entity, SlotType slotType, int index, ItemStack stack, ActionResponseBuffer buffer){ + for (var predicateId : predicateIds) { + var predicate = getPredicate(predicateId); + + if(predicate == null) continue; + + if(predicate instanceof EntitySlotValidator entityBasedPredicate) { + entityBasedPredicate.isValidForSlot(entity, level, slotType, index, stack, buffer); + } else { + predicate.isValidForSlot(level, slotType, index, stack, buffer); + } + + if(buffer.canPerformAction() != ValidationState.IRRELEVANT) break; + } + + return buffer; + } + + private static TagKey getSlotTag(SlotType slotType) { + var location = UniqueSlotHandling.isUniqueSlot(slotType.name()) ? Identifier.parse(slotType.name()) : Accessories.of(slotType.name()); + + return TagKey.create(Registries.ITEM, location); + } + + static { + register(AccessoriesBaseData.ALL_PREDICATE_ID, (level, slotType, i, stack, buffer) -> { + buffer.respondWith(SlotValidatorReasons.ALWAYS_VALID); + }); + register(AccessoriesBaseData.NONE_PREDICATE_ID, (level, slotType, i, stack, buffer) -> { + buffer.respondWith(SlotValidatorReasons.ALWAYS_INVALID); + }); + register(AccessoriesBaseData.TAG_PREDICATE_ID, (level, slotType, i, stack, buffer) -> { + buffer.respondWith(new TagValidationResponse<>(stack.getItem().builtInRegistryHolder(), List.of(getSlotTag(slotType), AccessoriesTags.ANY_TAG), TagValidationResponse.ANY_MATCH)); + }); + register(AccessoriesBaseData.ATTRIBUTE_PREDICATE_ID, SlotValidator.withEntity((entity, level, slotType, index, stack, buffer) -> { + var bl = !AccessoryAttributeLogic.getAttributeModifiers(stack, entity, slotType.name(), index) + .getAttributeModifiers(false, true) + .isEmpty(); + + buffer.respondWith(ActionResponse.of(ValidationState.ofOrIrrelevant(bl), (callback, ctx, type) -> { + var infoType = (bl ? "include" : "excludes"); + + + if (type.isAdvanced() || ((io.wispforest.accessories.pond.TooltipFlagExtended) type).hasShiftDown()) { + callback.add(Accessories.translation("tooltip.validator.attribute.simple", infoType)); + } + })); + })); + register(AccessoriesBaseData.COMPONENT_PREDICATE_ID, (level, slotType, index, stack, buffer) -> { + var slotValidationData = stack.getOrDefault(AccessoriesDataComponents.SLOT_VALIDATION, AccessorySlotValidationComponent.EMPTY); + + if (slotValidationData.isEmpty()) return; + + buffer.respondWith(new SlotValidationResponse(slotType.name(), slotValidationData.validSlotOverrides(), slotValidationData.invalidSlotOverrides())); + }); + } +} diff --git a/common/src/main/java/io/wispforest/accessories/api/tooltip/ComponentBuilder.java b/common/src/main/java/io/wispforest/accessories/api/tooltip/ComponentBuilder.java new file mode 100644 index 000000000..9096bed92 --- /dev/null +++ b/common/src/main/java/io/wispforest/accessories/api/tooltip/ComponentBuilder.java @@ -0,0 +1,11 @@ +package io.wispforest.accessories.api.tooltip; + +import net.minecraft.network.chat.MutableComponent; + +/// +/// Helper interface to used to build a [MutableComponent] from passed in args. Useful for +/// static method returns for namespaced translation components. +/// +public interface ComponentBuilder { + MutableComponent withArgs(Object... args); +} diff --git a/common/src/main/java/io/wispforest/accessories/api/tooltip/FormattedTextBuilder.java b/common/src/main/java/io/wispforest/accessories/api/tooltip/FormattedTextBuilder.java new file mode 100644 index 000000000..cb191577c --- /dev/null +++ b/common/src/main/java/io/wispforest/accessories/api/tooltip/FormattedTextBuilder.java @@ -0,0 +1,23 @@ +package io.wispforest.accessories.api.tooltip; + +import net.minecraft.network.chat.FormattedText; + +import java.util.stream.Stream; + +/// +/// Base Interface for handling the building of text data into [FormattedText] [Stream]. Typically, +/// this is for when a tooltip data needs to wrapped or prefixed with some indentation for better +/// format or prevent to long of tooltips +/// +public interface FormattedTextBuilder { + + default Stream build(TextWrapper wrapper) { + return build(TextPrefixer.NONE, wrapper); + } + + /// + /// Using the prefixer and wrapper, build the given data into [FormattedText] typically + /// from a [TooltipAdder] instance. + /// + Stream build(TextPrefixer prefixer, TextWrapper wrapper); +} diff --git a/common/src/main/java/io/wispforest/accessories/api/tooltip/ListTooltipAdder.java b/common/src/main/java/io/wispforest/accessories/api/tooltip/ListTooltipAdder.java new file mode 100644 index 000000000..83d95e951 --- /dev/null +++ b/common/src/main/java/io/wispforest/accessories/api/tooltip/ListTooltipAdder.java @@ -0,0 +1,32 @@ +package io.wispforest.accessories.api.tooltip; + +import io.wispforest.accessories.api.tooltip.impl.ListTooltipEntry; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.FormattedText; + +import java.util.List; + +/// +/// Helper class used to collect Lists of [Component]'s for tooltip info mainly in formated entry lists +/// +public interface ListTooltipAdder extends TooltipAdder { + + default ListTooltipAdder createListedEntry() { + return createListedEntry(ListTooltipEntry.LIST_ENTRY, ListTooltipEntry.INDENT_ENTRY); + } + + /// + /// Create Nested list entry for list within a list data + /// + ListTooltipAdder createListedEntry(FormattedText entryStart, FormattedText entryIndent); + + /// + /// Check if there is any tooltip data exists within the children of the adder + /// + boolean isEmpty(); + + /// + /// Get the size of the current adder tooltip data from within its children + /// + int unpackedSize(); +} diff --git a/common/src/main/java/io/wispforest/accessories/api/tooltip/TextPrefixer.java b/common/src/main/java/io/wispforest/accessories/api/tooltip/TextPrefixer.java new file mode 100644 index 000000000..1324ddbd2 --- /dev/null +++ b/common/src/main/java/io/wispforest/accessories/api/tooltip/TextPrefixer.java @@ -0,0 +1,18 @@ +package io.wispforest.accessories.api.tooltip; + +import net.minecraft.network.chat.FormattedText; + +/// +/// Helper object used to append to the start of a given [FormattedText] either for +/// indentation and/or list entry marker text. +/// +public interface TextPrefixer { + TextPrefixer NONE = (mode, index, text) -> text; + + FormattedText handle(EntryMode mode, int index, FormattedText text); + + enum EntryMode { + START, + INDENT + } +} diff --git a/common/src/main/java/io/wispforest/accessories/api/tooltip/TextWrapper.java b/common/src/main/java/io/wispforest/accessories/api/tooltip/TextWrapper.java new file mode 100644 index 000000000..b2580c3b0 --- /dev/null +++ b/common/src/main/java/io/wispforest/accessories/api/tooltip/TextWrapper.java @@ -0,0 +1,45 @@ +package io.wispforest.accessories.api.tooltip; + +import io.wispforest.accessories.AccessoriesClientInternals; +import net.minecraft.network.chat.FormattedText; +import net.minecraft.network.chat.Style; + +import java.util.stream.Stream; + +/// +/// Helper object to wrap [FormattedText] to prevent it from being too long. +/// +public abstract class TextWrapper { + public static final TextWrapper NONE = new NoWrapping(); + + public static TextWrapper createWrapper(int maxWidth) { + return createWrapper(maxWidth, Style.EMPTY); + } + + public static TextWrapper createWrapper(int maxWidth, Style overrideStyle) { + return AccessoriesClientInternals.getInstance().createWrapper(maxWidth, overrideStyle); + } + + public abstract Stream wrap(FormattedText text); + + public abstract int hashCode(); + + public abstract boolean equals(Object obj); +} + +class NoWrapping extends TextWrapper { + @Override + public Stream wrap(FormattedText text) { + return Stream.of(text); + } + + @Override + public int hashCode() { + return 0; + } + + @Override + public boolean equals(Object obj) { + return obj instanceof NoWrapping; + } +} diff --git a/common/src/main/java/io/wispforest/accessories/api/tooltip/TooltipAdder.java b/common/src/main/java/io/wispforest/accessories/api/tooltip/TooltipAdder.java new file mode 100644 index 000000000..a60e866d2 --- /dev/null +++ b/common/src/main/java/io/wispforest/accessories/api/tooltip/TooltipAdder.java @@ -0,0 +1,15 @@ +package io.wispforest.accessories.api.tooltip; + +import net.minecraft.network.chat.Component; + +/// +/// Helper class used to collect [Component]'s for tooltip info +/// +public interface TooltipAdder extends FormattedTextBuilder { + + /// + /// Add the given component as a new line entry for the adder + /// + TooltipAdder add(Component component); +} + diff --git a/common/src/main/java/io/wispforest/accessories/api/tooltip/TooltipComponentBuilder.java b/common/src/main/java/io/wispforest/accessories/api/tooltip/TooltipComponentBuilder.java new file mode 100644 index 000000000..6592ac949 --- /dev/null +++ b/common/src/main/java/io/wispforest/accessories/api/tooltip/TooltipComponentBuilder.java @@ -0,0 +1,35 @@ +package io.wispforest.accessories.api.tooltip; + +import io.wispforest.accessories.AccessoriesClientInternals; +import net.minecraft.network.chat.FormattedText; +import org.jetbrains.annotations.ApiStatus; + +import java.util.Collection; +import java.util.stream.Stream; + +/// +/// Low level way of building tooltips into [ClientTooltipComponent][net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent]'s +/// +@ApiStatus.NonExtendable +public interface TooltipComponentBuilder extends TooltipComponentHolder { + + static TooltipComponentBuilder of() { + return AccessoriesClientInternals.getInstance().createTooltipBuilder(); + } + + TooltipComponentBuilder divider(int height); + + TooltipComponentBuilder divider(); + + TooltipComponentBuilder add(TooltipComponentBuilder builder); + + TooltipComponentBuilder add(FormattedText text); + + TooltipComponentBuilder addAll(Collection text); + + TooltipComponentBuilder addAll(TextPrefixer prefixer, FormattedTextBuilder builder); + + TooltipComponentBuilder add(TooltipComponentHolder holder); + + boolean isEmpty(); +} diff --git a/common/src/main/java/io/wispforest/accessories/api/tooltip/TooltipComponentHolder.java b/common/src/main/java/io/wispforest/accessories/api/tooltip/TooltipComponentHolder.java new file mode 100644 index 000000000..9f839a287 --- /dev/null +++ b/common/src/main/java/io/wispforest/accessories/api/tooltip/TooltipComponentHolder.java @@ -0,0 +1,4 @@ +package io.wispforest.accessories.api.tooltip; + +public interface TooltipComponentHolder { +} diff --git a/common/src/main/java/io/wispforest/accessories/api/tooltip/TooltipInfoProvider.java b/common/src/main/java/io/wispforest/accessories/api/tooltip/TooltipInfoProvider.java new file mode 100644 index 000000000..6419654c3 --- /dev/null +++ b/common/src/main/java/io/wispforest/accessories/api/tooltip/TooltipInfoProvider.java @@ -0,0 +1,15 @@ +package io.wispforest.accessories.api.tooltip; + +import net.minecraft.world.item.Item; +import net.minecraft.world.item.TooltipFlag; + +public interface TooltipInfoProvider { + + static E gatherInfo(TooltipInfoProvider provider, E adder, Item.TooltipContext ctx, TooltipFlag type) { + provider.addInfo(adder, ctx, type); + + return adder; + } + + void addInfo(A adder, Item.TooltipContext ctx, TooltipFlag type); +} diff --git a/common/src/main/java/io/wispforest/accessories/api/tooltip/impl/ListTooltipEntry.java b/common/src/main/java/io/wispforest/accessories/api/tooltip/impl/ListTooltipEntry.java new file mode 100644 index 000000000..4fbd574e7 --- /dev/null +++ b/common/src/main/java/io/wispforest/accessories/api/tooltip/impl/ListTooltipEntry.java @@ -0,0 +1,130 @@ +package io.wispforest.accessories.api.tooltip.impl; + +import io.wispforest.accessories.Accessories; +import io.wispforest.accessories.api.tooltip.ListTooltipAdder; +import io.wispforest.accessories.api.tooltip.TextPrefixer; +import io.wispforest.accessories.api.tooltip.TextWrapper; +import io.wispforest.accessories.api.tooltip.TooltipAdder; +import io.wispforest.accessories.utils.CollectionUtils; +import io.wispforest.accessories.utils.ComponentOps; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.FormattedText; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.stream.Stream; + +public class ListTooltipEntry implements ListTooltipAdder, TooltipAdder, TextPrefixer { + + public static final Component LIST_ENTRY = Accessories.translation("tooltip.equipment_reasoning.list_entry"); + public static final Component INDENT_ENTRY = Accessories.translation("tooltip.equipment_reasoning.indent_entry"); + + protected final List entries = new ArrayList<>(); + + protected final @Nullable TextPrefixer overridePrefixer; + + public final FormattedText entryStart; + public final FormattedText entryIndent; + + protected ListTooltipEntry() { + this(LIST_ENTRY, INDENT_ENTRY); + } + + protected ListTooltipEntry(FormattedText entryStart, FormattedText entryIndent) { + this(null, entryStart, entryIndent); + } + + protected ListTooltipEntry(@Nullable TextPrefixer overridePrefixer, FormattedText entryStart, FormattedText entryIndent) { + this.overridePrefixer = overridePrefixer; + this.entryStart = entryStart; + this.entryIndent = entryIndent; + } + + public static ListTooltipEntry of() { + return new ListTooltipEntry(); + } + + public static ListTooltipEntry flatMap() { + return new ListTooltipEntry(TextPrefixer.NONE, LIST_ENTRY, INDENT_ENTRY); + } + + /// + /// Add a [Component] to the list as a separate entry + /// + public ListTooltipEntry add(Component component) { + entries.add(new TooltipEntry(List.of(component))); + + return this; + } + + /// + /// Start a new entry in the list, the returned callback allows for additions to the entry group + /// + public TooltipAdder adder() { + var adder = new TooltipEntry(); + + entries.add(adder); + + return adder; + } + + @Override + public ListTooltipEntry createListedEntry(FormattedText entryStart, FormattedText entryIndent) { + var adder = new ListTooltipEntry(entryStart, entryIndent); + + entries.add(adder); + + return adder; + } + + public boolean isEmpty() { + for (var entry : entries) { + if (!(entry instanceof ListTooltipAdder adder)) return false; + if (!adder.isEmpty()) return false; + } + + return true; + } + + public int unpackedSize() { + return entries.stream() + .mapToInt(adder -> adder instanceof ListTooltipAdder list ? list.unpackedSize() : 1) + .sum(); + } + + private @Nullable Integer baseHash = null; + + @Override + public int hashCode() { + if (baseHash == null) baseHash = Objects.hash(ComponentOps.getHashCode(entryStart), ComponentOps.getHashCode(entryIndent)); + + return Objects.hash(baseHash, this.entries.hashCode()); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (!(obj instanceof ListTooltipEntry other)) return false; + return this.hashCode() == other.hashCode(); + } + + //-- + + @Override + public FormattedText handle(EntryMode mode, int index, FormattedText text) { + return FormattedText.composite(mode == TextPrefixer.EntryMode.START ? entryStart : entryIndent, text); + } + + @Override + public Stream build(TextPrefixer prefixer, TextWrapper wrapper) { + return entries.stream() + .flatMap(adder -> { + var texts = adder.build(overridePrefixer != null ? overridePrefixer : this, wrapper); + + return CollectionUtils.mapWithIndex(texts, (index, text) -> prefixer.handle(TextPrefixer.EntryMode.INDENT, index, text)); + }); + } +} diff --git a/common/src/main/java/io/wispforest/accessories/api/tooltip/impl/TooltipEntry.java b/common/src/main/java/io/wispforest/accessories/api/tooltip/impl/TooltipEntry.java new file mode 100644 index 000000000..d50c9db6a --- /dev/null +++ b/common/src/main/java/io/wispforest/accessories/api/tooltip/impl/TooltipEntry.java @@ -0,0 +1,87 @@ +package io.wispforest.accessories.api.tooltip.impl; + +import io.wispforest.accessories.api.tooltip.TextPrefixer; +import io.wispforest.accessories.api.tooltip.TextWrapper; +import io.wispforest.accessories.api.tooltip.TooltipAdder; +import io.wispforest.accessories.utils.CollectionUtils; +import io.wispforest.accessories.utils.ComponentOps; +import net.minecraft.locale.Language; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.FormattedText; +import net.minecraft.network.chat.Style; +import net.minecraft.util.FormattedCharSequence; +import net.minecraft.util.FormattedCharSink; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.stream.Stream; + +public class TooltipEntry implements TooltipAdder { + + protected TooltipEntry() { + this(new ArrayList<>()); + } + + protected TooltipEntry(List entries) { + this.entries = entries; + } + + public static TooltipEntry of() { + return new TooltipEntry(); + } + + private final List entries; + + @Override + public TooltipAdder add(Component component) { + entries.add(component); + + resetHash(); + + return this; + } + + private boolean shouldCreateHash = true; + private int hashCode = 0; + + protected void resetHash() { + shouldCreateHash = true; + } + + @Override + public int hashCode() { + if (shouldCreateHash) { + var hashes = new Object[entries.size()]; + for (int i = 0; i < entries.size(); i++) hashes[i] = ComponentOps.getHashCode(entries.get(i)); + hashCode = Objects.hash(hashes); + shouldCreateHash = false; + } + + return hashCode; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (!(obj instanceof TooltipEntry other)) return false; + return this.hashCode() == other.hashCode(); + } + + public List entries() { + return Collections.unmodifiableList(entries); + } + + @Override + public Stream build(TextPrefixer prefixer, TextWrapper wrapper) { + return this.entries.stream().flatMap(entry -> { + return CollectionUtils.mapWithIndex(wrapper.wrap(entry), (innerIndex, wrappedText) -> { + var mode = innerIndex == 0 ? TextPrefixer.EntryMode.START : TextPrefixer.EntryMode.INDENT; + + return prefixer.handle(mode, innerIndex, wrappedText); + }); + }); + } +} diff --git a/common/src/main/java/io/wispforest/accessories/client/AccessoriesClient.java b/common/src/main/java/io/wispforest/accessories/client/AccessoriesClient.java index 16b9be826..e1709c874 100644 --- a/common/src/main/java/io/wispforest/accessories/client/AccessoriesClient.java +++ b/common/src/main/java/io/wispforest/accessories/client/AccessoriesClient.java @@ -5,7 +5,11 @@ import io.wispforest.accessories.AccessoriesClientInternals; import io.wispforest.accessories.api.AccessoriesCapability; import io.wispforest.accessories.api.client.AccessoriesRendererRegistry; +import io.wispforest.accessories.api.client.tooltip.TextWrapperImpl; +import io.wispforest.accessories.api.client.tooltip.TooltipComponentBuilderImpl; import io.wispforest.accessories.api.client.screen.AccessoriesScreenTransitionHelper; +import io.wispforest.accessories.api.tooltip.TextWrapper; +import io.wispforest.accessories.api.tooltip.TooltipComponentBuilder; import io.wispforest.accessories.client.gui.AccessoriesScreenBase; import io.wispforest.accessories.client.gui.components.AccessoriesScreenSettingsLayout; import io.wispforest.accessories.client.gui.components.ComponentUtils; @@ -21,7 +25,7 @@ import io.wispforest.accessories.networking.AccessoriesNetworking; import io.wispforest.accessories.networking.holder.SyncOptionChange; import io.wispforest.accessories.networking.server.ScreenOpen; -import io.wispforest.accessories.pond.TooltipFlagExtension; +import io.wispforest.accessories.pond.TooltipFlagExtended; import io.wispforest.owo.config.ui.ConfigScreenProviders; import io.wispforest.owo.config.ui.OptionComponentFactory; import io.wispforest.owo.config.ui.OptionComponents; @@ -29,9 +33,9 @@ import io.wispforest.owo.config.ui.component.SearchAnchorComponent; import io.wispforest.owo.ui.base.BaseOwoScreen; import io.wispforest.owo.ui.component.ButtonComponent; -import io.wispforest.owo.ui.component.Components; +import io.wispforest.owo.ui.component.UIComponents; import io.wispforest.owo.ui.component.LabelComponent; -import io.wispforest.owo.ui.container.Containers; +import io.wispforest.owo.ui.container.UIContainers; import io.wispforest.owo.ui.container.FlowLayout; import io.wispforest.owo.ui.core.*; import io.wispforest.owo.ui.layers.Layers; @@ -40,19 +44,19 @@ import net.fabricmc.fabric.api.event.Event; import net.fabricmc.fabric.api.event.EventFactory; import net.minecraft.ChatFormatting; -import net.minecraft.Util; +import net.minecraft.util.Util; import net.minecraft.client.KeyMapping; import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; import net.minecraft.client.gui.screens.inventory.CreativeModeInventoryScreen; +import net.minecraft.client.gui.screens.inventory.InventoryScreen; import net.minecraft.client.resources.language.I18n; import net.minecraft.core.component.DataComponents; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.Style; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.projectile.ProjectileUtil; -import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.item.BannerItem; import net.minecraft.world.item.CreativeModeTab; import net.minecraft.world.item.ItemStack; @@ -66,6 +70,7 @@ import java.util.Objects; import java.util.function.Consumer; import java.util.function.Function; +import java.util.function.Predicate; import static io.wispforest.accessories.Accessories.MODID; @@ -74,6 +79,7 @@ public class AccessoriesClient { public static final KeyMapping.Category KEY_CATEGORY = KeyMapping.Category.register(Accessories.of("main")); public static final KeyMapping OPEN_SCREEN = new KeyMapping(MODID + ".key.open_accessories_screen", GLFW.GLFW_KEY_H, KEY_CATEGORY); + public static final KeyMapping OPEN_OTHERS_SCREEN = new KeyMapping(MODID + ".key.open_others_accessories_screen", GLFW.GLFW_KEY_H, KEY_CATEGORY); //public static final ShaderProgram BLIT_SHADER_KEY = new ShaderProgram(Accessories.of("core/fish"), DefaultVertexFormat.BLIT_SCREEN, ShaderDefines.EMPTY); @@ -113,7 +119,7 @@ public static void initConfigStuff() { btnLayout.removeChild(tempBtn); - var toggleButton = (ButtonComponent) Components.button(Component.literal("Edit"), btn -> {}) + var toggleButton = (ButtonComponent) UIComponents.button(Component.literal("Edit"), btn -> {}) .verticalSizing(tempBtn.verticalSizing().get()) .horizontalSizing(tempBtn.horizontalSizing().get()); @@ -125,30 +131,30 @@ public static void initConfigStuff() { var newScreen = new BaseOwoScreen() { @Override protected @NotNull OwoUIAdapter createAdapter() { - return OwoUIAdapter.create(this, Containers::verticalFlow); + return OwoUIAdapter.create(this, UIContainers::verticalFlow); } @Override protected void build(FlowLayout rootComponent) { rootComponent.child( - Containers.verticalFlow(Sizing.fixed(178), Sizing.content()) + UIContainers.verticalFlow(Sizing.fixed(178), Sizing.content()) .child( - Containers.horizontalFlow(Sizing.content(), Sizing.fixed(14)) + UIContainers.horizontalFlow(Sizing.content(), Sizing.fixed(14)) .child( - Containers.horizontalFlow(Sizing.expand(), Sizing.content()) + UIContainers.horizontalFlow(Sizing.expand(), Sizing.content()) .child( - Components.label( + UIComponents.label( Component.literal("Default Screen Options") ) ).horizontalAlignment(HorizontalAlignment.LEFT) ) .child( - Components.button(Component.literal("Back"), btn -> onClose()) + UIComponents.button(Component.literal("Back"), btn -> onClose()) .verticalSizing(Sizing.fixed(14)) ).verticalAlignment(VerticalAlignment.CENTER) ) .child( - Containers.verticalFlow(Sizing.fill(), Sizing.fixed(186)) + UIContainers.verticalFlow(Sizing.fill(), Sizing.fixed(186)) .child(new AccessoriesScreenSettingsLayout(holderValue.getValue(), this::component).shouldNetworkSync(false).updateLive(true)) .padding(Insets.of(1)) .surface(ComponentUtils.getInsetPanelSurface()) @@ -178,8 +184,7 @@ public void onClose() { client.mouseHandler.releaseMouse(); KeyMapping.releaseAll(); - newScreen.init(client, client.getWindow().getGuiScaledWidth(), client.getWindow().getGuiScaledHeight()); - client.noRender = false; + newScreen.init(client.getWindow().getGuiScaledWidth(), client.getWindow().getGuiScaledHeight()); }); optionComponent.child(new SearchAnchorComponent( @@ -218,11 +223,11 @@ public void onClose() { var annotationData = option.backingField().field().getAnnotation(Structured.class); var title = net.minecraft.network.chat.Component.translatable("text.config." + option.configName() + ".option." + option.key().asString()); - var titleLayout = Containers.horizontalFlow(Sizing.content(), Sizing.content()); + var titleLayout = UIContainers.horizontalFlow(Sizing.content(), Sizing.content()); titleLayout.padding(Insets.of(5, 5, 5, 0)); title = title.copy().withStyle(ChatFormatting.UNDERLINE); - titleLayout.child(Components.label(title)); + titleLayout.child(UIComponents.label(title)); var component = StructOptionContainer.of(model, option, builder, annotationData.sideBySide()); @@ -233,12 +238,12 @@ public void onClose() { () -> component.parsedValue().toString() )); - var mainLayout = Containers.verticalFlow(Sizing.content(), Sizing.content()); + var mainLayout = UIContainers.verticalFlow(Sizing.content(), Sizing.content()); mainLayout.child(titleLayout) .child(component); - return new OptionComponentFactory.Result(mainLayout, component); + return new OptionComponentFactory.Result(mainLayout, component); }); })); @@ -273,14 +278,31 @@ public void onClose() { public static void init(){ AccessoriesClientInternals.setInstance(new AccessoriesClientInternals() { @Override - public TooltipFlag createTooltipFlag(TooltipFlag flag) { - var client = Minecraft.getInstance(); + public TooltipComponentBuilder createTooltipBuilder() { + return new TooltipComponentBuilderImpl(); + } + + @Override + public TextWrapper createWrapper(int maxWidth, Style overrideStyle) { + return new TextWrapperImpl(maxWidth, overrideStyle); + } + + @Override + public TooltipFlag createTooltipFlag() { + return TooltipFlagExtended.create(Minecraft.getInstance().options.advancedItemTooltips); + } - var modifiers = (client.hasShiftDown() ? GLFW.GLFW_MOD_SHIFT : 0) - | (client.hasControlDown() ? EDIT_SHORTCUT_KEY_MODIFIER : 0) - | (client.hasAltDown() ? GLFW.GLFW_MOD_ALT : 0); + @Override + public int createBitFlag() { + var inst = Minecraft.getInstance(); + return createBitFlag(inst.hasShiftDown(), inst.hasControlDown(), inst.hasAltDown()); + } - return TooltipFlagExtension.createFlag(flag, modifiers); + @Override + public int createBitFlag(boolean hasShift, boolean hasControl, boolean hasAlt) { + return (hasShift ? GLFW.GLFW_MOD_SHIFT : 0) + | (hasControl ? EDIT_SHORTCUT_KEY_MODIFIER : 0) + | (hasAlt ? GLFW.GLFW_MOD_ALT : 0); } }); @@ -288,7 +310,12 @@ public TooltipFlag createTooltipFlag(TooltipFlag flag) { if (!success) return; // LOADING PROBLEM HAS OCCURRED SO THINGS WILL GO WRONG IF WE TRY DOING OUR STUFF BuiltInRegistries.ITEM.forEach(item -> { - var defaultStack = item.getDefaultInstance(); + ItemStack defaultStack; + try { + defaultStack = item.getDefaultInstance(); + } catch (NullPointerException e) { + return; // Components not bound yet for this item, skip + } if (item instanceof BannerItem || defaultStack.has(DataComponents.GLIDER)) { if (!AccessoriesRendererRegistry.hasRenderer(item)) { @@ -304,25 +331,66 @@ public TooltipFlag createTooltipFlag(TooltipFlag flag) { initLayer(); } - public static void openScreenFromKey() { + public static boolean isInventoryKey(Predicate predicate) { + return predicate.test(OPEN_SCREEN) || predicate.test(OPEN_OTHERS_SCREEN); + } + + public static void handleKeyMappings(Minecraft client) { + while (AccessoriesClient.OPEN_SCREEN.consumeClick()){ + var player = client.player; + + if (Accessories.config().screenOptions.prioritizeCreativeScreen() && player != null && player.isCreative()) { + if (client.gameMode.isServerControlledInventory()) { + player.sendOpenInventory(); + } else { + client.getTutorial().onOpenInventory(); + client.setScreen(new InventoryScreen(player)); + } + + return; + } + + AccessoriesClient.openScreenFromKey(AccessoriesClient.OPEN_SCREEN); + } + + if (!AccessoriesClient.OPEN_OTHERS_SCREEN.same(AccessoriesClient.OPEN_SCREEN)) { + while (AccessoriesClient.OPEN_OTHERS_SCREEN.consumeClick()){ + AccessoriesClient.openScreenFromKey(AccessoriesClient.OPEN_OTHERS_SCREEN); + } + } + } + + public static void openScreenFromKey(KeyMapping keyMapping) { var minecraft = Minecraft.getInstance(); var currentScreen = minecraft.screen; if (currentScreen instanceof AccessoriesScreenBase) { minecraft.setScreen(null); } else if (currentScreen == null) { - AccessoriesClient.attemptToOpenScreen(minecraft.player.isShiftKeyDown() ? EntityTarget.LOOKING_ENTITY : EntityTarget.PLAYER); - } else { - LivingEntity targetEntity = null; - - if (currentScreen instanceof AbstractContainerScreen containerScreen) { - targetEntity = AccessoriesScreenTransitionHelper.getTargetEntity((AbstractContainerScreen) containerScreen); + EntityTarget target; + + if (keyMapping == OPEN_OTHERS_SCREEN) { + target = EntityTarget.LOOKING_ENTITY; + } else if (!OPEN_SCREEN.same(OPEN_OTHERS_SCREEN)) { + target = EntityTarget.PLAYER; + } else { + target = minecraft.player.isShiftKeyDown() ? EntityTarget.LOOKING_ENTITY : EntityTarget.PLAYER; } - if (targetEntity == null) targetEntity = minecraft.player; - - AccessoriesClient.attemptToOpenScreenFromEntity(targetEntity); + AccessoriesClient.attemptToOpenScreen(target); } + // TODO: REMOVE AFTER MORE THINKING AS THIS KIND OF DOSE NOT MAKE SENSE AND WILL MOST LIKELY NOT BE AS USEFUL BUT MUST THINK ABOUT SUCH A BIT +// else { +// LivingEntity targetEntity = null; +// +// if (currentScreen instanceof AbstractContainerScreen containerScreen) { +// targetEntity = AccessoriesScreenTransitionHelper.getTargetEntity((AbstractContainerScreen) containerScreen); +// } +// +// if (targetEntity == null) targetEntity = minecraft.player; +// +// AccessoriesClient.attemptToOpenScreenFromEntity(targetEntity); +// } } private static void attemptAction(Consumer consumer) { @@ -377,9 +445,7 @@ public static boolean attemptToOpenScreen(EntityTarget entityTarget) { : AccessoriesScreenTransitionHelper.getTargetEntity(player); if(targetEntity == null) { - if (entityTarget.equals(EntityTarget.PLAYER)){ - return attemptToOpenScreenFromEntity(player); - } else if (entityTarget.equals(EntityTarget.LOOKING_ENTITY)) { + if (entityTarget.equals(EntityTarget.LOOKING_ENTITY)) { var result = ProjectileUtil.getHitResultOnViewVector(player, e -> e instanceof LivingEntity, player.entityInteractionRange()); if (result instanceof EntityHitResult entitResult && entitResult.getEntity() instanceof LivingEntity living) { @@ -388,9 +454,11 @@ public static boolean attemptToOpenScreen(EntityTarget entityTarget) { } } - if (targetEntity != null && !EntitySlotLoader.getEntitySlots(targetEntity).isEmpty()) return attemptToOpenScreenFromEntity(targetEntity); + if (targetEntity == null || entityTarget.equals(EntityTarget.PLAYER)){ + return attemptToOpenScreenFromEntity(player); + } - return false; + return !EntitySlotLoader.getEntitySlots(targetEntity).isEmpty() && attemptToOpenScreenFromEntity(targetEntity); } public static boolean attemptToOpenScreenFromEntity(LivingEntity targetingEntity) { @@ -402,7 +470,7 @@ public static boolean attemptToOpenScreenFromEntity(LivingEntity targetingEntity var options = AccessoriesPlayerOptionsHolder.getOptions(player); if(slots.isEmpty() && !options.getDefaultedData(PlayerOptions.SHOW_UNUSED_SLOTS) && !displayUnusedSlotWarning && !Accessories.config().clientOptions.disableEmptySlotScreenError()) { - player.displayClientMessage(Component.literal("[Accessories]: No Used Slots found by any mod directly, the screen will show empty unless a item is found to implement slots!"), false); + player.sendSystemMessage(Component.literal("[Accessories]: No Used Slots found by any mod directly, the screen will show empty unless a item is found to implement slots!")); displayUnusedSlotWarning = true; } @@ -438,7 +506,7 @@ public static void attemptToOpenSelectionScreen(int entityId, boolean targetLook public static void initLayer() { AccessoriesScreenTransitionHelper.init(); - Layers.add(Containers::verticalFlow, instance -> { + Layers.add(UIContainers::verticalFlow, instance -> { // THIS IS HERE TO HAVE UPDATE POSITION EVERY FRAME BEFORE RENDER TO STOP STUPID POSITIONING PROBLEMS!!! instance.aggressivePositioning = true; @@ -448,7 +516,7 @@ public static void initLayer() { if (injectionData == null) return; - var button = (ButtonComponent) Components.button(Component.literal(""), (btn) -> { + var button = (ButtonComponent) UIComponents.button(Component.literal(""), (btn) -> { var target = AccessoriesScreenTransitionHelper.getTargetEntity(instance.screen); if (target == null) target = Minecraft.getInstance().player; diff --git a/common/src/main/java/io/wispforest/accessories/client/AccessoriesPipelines.java b/common/src/main/java/io/wispforest/accessories/client/AccessoriesPipelines.java index 9994fde86..bf7b80452 100644 --- a/common/src/main/java/io/wispforest/accessories/client/AccessoriesPipelines.java +++ b/common/src/main/java/io/wispforest/accessories/client/AccessoriesPipelines.java @@ -1,23 +1,24 @@ package io.wispforest.accessories.client; import com.mojang.blaze3d.pipeline.BlendFunction; +import com.mojang.blaze3d.pipeline.ColorTargetState; import com.mojang.blaze3d.pipeline.RenderPipeline; import com.mojang.blaze3d.pipeline.TextureTarget; -import com.mojang.blaze3d.platform.DepthTestFunction; +import com.mojang.blaze3d.pipeline.DepthStencilState; +import com.mojang.blaze3d.platform.CompareOp; import com.mojang.blaze3d.platform.DestFactor; import com.mojang.blaze3d.platform.SourceFactor; +import com.mojang.blaze3d.shaders.UniformType; import com.mojang.blaze3d.vertex.DefaultVertexFormat; import com.mojang.blaze3d.vertex.VertexFormat; import io.wispforest.accessories.Accessories; import io.wispforest.owo.ui.core.Color; import io.wispforest.owo.ui.core.OwoUIPipelines; import io.wispforest.owo.ui.event.WindowResizeCallback; -import net.minecraft.Util; +import net.minecraft.util.Util; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.RenderPipelines; -import net.minecraft.client.renderer.RenderStateShard; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import java.util.function.BiFunction; import java.util.function.Consumer; @@ -25,19 +26,18 @@ public class AccessoriesPipelines { - public static final RenderType.CompositeRenderType HSV_GUI = RenderType.create( - "accessories:hsv_gui", - 786432, - OwoUIPipelines.GUI_HSV, - RenderType.CompositeState.builder().createCompositeState(false) - ); + // Inline equivalent of private RenderPipelines.MATRICES_PROJECTION_SNIPPET + private static final RenderPipeline.Snippet MATRICES_PROJECTION_SNIPPET = RenderPipeline.builder() + .withUniform("DynamicTransforms", UniformType.UNIFORM_BUFFER) + .withUniform("Projection", UniformType.UNIFORM_BUFFER) + .buildSnippet(); - public static final RenderPipeline.Snippet SPECTRUM_SNIPPET = RenderPipeline.builder(RenderPipelines.MATRICES_PROJECTION_SNIPPET) + public static final RenderPipeline.Snippet SPECTRUM_SNIPPET = RenderPipeline.builder(MATRICES_PROJECTION_SNIPPET) .withFragmentShader(Accessories.of("core/spectrum_position_tex")) .withVertexShader(Accessories.of("core/spectrum_position_tex")) .withVertexFormat(DefaultVertexFormat.POSITION_COLOR, VertexFormat.Mode.QUADS) - .withBlend(BlendFunction.TRANSLUCENT) - .withDepthTestFunction(DepthTestFunction.LEQUAL_DEPTH_TEST) + .withColorTargetState(new ColorTargetState(BlendFunction.TRANSLUCENT)) + .withDepthStencilState(new DepthStencilState(CompareOp.LESS_THAN_OR_EQUAL, true)) .withSampler("InputSampler") .buildSnippet(); @@ -45,40 +45,35 @@ public class AccessoriesPipelines { .withLocation(Accessories.of("pipeline/spectrum")) .build(); - public static final Function SPECTRUM_GUI = Util.memoize( - resourceLocation -> RenderType.create( - "accessories:spectrum_gui", - 786432, - SPECTRUM, - RenderType.CompositeState.builder() - .setTextureState(new RenderStateShard.TextureStateShard(resourceLocation, false)) - .createCompositeState(false) - ) - ); - - public static final RenderPipeline COLORED_GUI_TEXTURED_PIPE = RenderPipeline.builder(RenderPipelines.GUI_TEXTURED_SNIPPET) + // Inline equivalent of private RenderPipelines.GUI_TEXTURED_SNIPPET + private static final RenderPipeline.Snippet GUI_TEXTURED_SNIPPET = RenderPipeline.builder(MATRICES_PROJECTION_SNIPPET) + .withVertexShader("core/gui") + .withFragmentShader("core/gui") + .withVertexFormat(DefaultVertexFormat.POSITION_TEX_COLOR, VertexFormat.Mode.QUADS) + .withSampler("Sampler0") + .withColorTargetState(new ColorTargetState(BlendFunction.TRANSLUCENT)) + .buildSnippet(); + + public static final RenderPipeline COLORED_GUI_TEXTURED_PIPE = RenderPipeline.builder(GUI_TEXTURED_SNIPPET) .withLocation(Accessories.of("pipeline/colored_gui_textured")) - .withColorWrite(true) - .withDepthTestFunction(DepthTestFunction.LEQUAL_DEPTH_TEST) - .withBlend(new BlendFunction(SourceFactor.ONE, DestFactor.ONE)) + .withDepthStencilState(new DepthStencilState(CompareOp.LESS_THAN_OR_EQUAL, true)) + .withColorTargetState(new ColorTargetState(new BlendFunction(SourceFactor.ONE, DestFactor.ONE))) .build(); - public static final BiFunction COLORED_GUI_TEXTURED = Util.memoize( - (color, resourceLocation) -> { - return RenderType.create( - "accessories:colored_gui_textured", - 786432, - COLORED_GUI_TEXTURED_PIPE, - RenderType.CompositeState.builder() - .setTextureState(new RenderStateShard.TextureStateShard(resourceLocation, false)) - /*.setTexturingState(new RenderStateShard.TexturingStateShard("setting_shader_color", () -> { - RenderSystem.setShaderColor(color.red(), color.green(), color.blue(), 1f); - }, () -> { - RenderSystem.setShaderColor(1f, 1f, 1f, 1f); - }))*/ - .createCompositeState(false)); - } - ); + // Using OwoUIPipelines.GUI_HSV directly instead of creating RenderType + public static RenderPipeline getHsvGuiPipeline() { + return OwoUIPipelines.GUI_HSV; + } + + // Using SPECTRUM pipeline directly + public static RenderPipeline getSpectrumPipeline() { + return SPECTRUM; + } + + // Using COLORED_GUI_TEXTURED_PIPE directly + public static RenderPipeline getColoredGuiTexturedPipeline() { + return COLORED_GUI_TEXTURED_PIPE; + } public static void registerPipelines(Consumer pipelineRegister) { pipelineRegister.accept(SPECTRUM); @@ -87,34 +82,6 @@ public static void registerPipelines(Consumer pipelineRegister) private static TextureTarget BUFFER = null; - private static Color SHADER_COLOR = null; - // TODO: FIX THIS WHEN WE CARE ENOUGH TO RESOLVE ISSUES -// private static final RenderType HOVER_EFFECT = RenderType.create( -// "accessories_hover_effect", -// 786432, -// RenderPipelines.GUI_TEXTURED_OVERLAY, -// RenderType.CompositeState.builder().setTextureState(new RenderStateShard.EmptyTextureStateShard( -// () -> { -// RenderSystem.setShaderTexture(0, getOrCreateBuffer().getColorTexture()); -// if (SHADER_COLOR != null) { -// RenderSystem.setShaderColor(SHADER_COLOR.red(), SHADER_COLOR.green(), SHADER_COLOR.blue(), SHADER_COLOR.alpha()); -// } -// }, -// () -> { -// if (SHADER_COLOR != null) { -// RenderSystem.setShaderColor(1, 1, 1, 1); -// SHADER_COLOR = null; -// } -// } -// )).createCompositeState(false) -// ); - -// public static RenderType setupHoverEffect(Color color) { -// SHADER_COLOR = color; -// -// return HOVER_EFFECT; -// } - public static TextureTarget getOrCreateBuffer() { try { if (BUFFER == null) { diff --git a/common/src/main/java/io/wispforest/accessories/client/AccessoriesRenderLayer.java b/common/src/main/java/io/wispforest/accessories/client/AccessoriesRenderLayer.java index ec162328e..f2b83c9af 100644 --- a/common/src/main/java/io/wispforest/accessories/client/AccessoriesRenderLayer.java +++ b/common/src/main/java/io/wispforest/accessories/client/AccessoriesRenderLayer.java @@ -49,11 +49,11 @@ public AccessoriesRenderLayer(RenderLayerParent renderLayerParent) { public void submit(PoseStack poseStack, SubmitNodeCollector submitNodeCollector, int light, S entityState, float f, float g) { var client = Minecraft.getInstance(); - var states = entityState.getStateData(AccessoriesRenderStateKeys.ACCESSORY_RENDER_STATES); + var states = ((io.wispforest.accessories.pond.AccessoriesRenderStateAPImpl) entityState).getStateData(AccessoriesRenderStateKeys.ACCESSORY_RENDER_STATES); if (states == null) return; - entityState.setStateData(AccessoriesRenderStateKeys.LIGHT, light); + ((io.wispforest.accessories.pond.AccessoriesRenderStateAPImpl) entityState).setStateData(AccessoriesRenderStateKeys.LIGHT, light); var funkyRenderState = AccessoriesFunkyRenderingState.INSTANCE; @@ -131,7 +131,7 @@ public void submit(PoseStack poseStack, SubmitNodeCollector submitNodeCollector, try { renderer.render(accessoryRenderState, entityState, getParentModel(), poseStack, submitNodeCollector); } catch (Throwable e) { - AccessoryRendererErrorCache.logIfTimeAllotted(entityState.getEntityUUIDForState(), stack, renderer, e); + AccessoryRendererErrorCache.logIfTimeAllotted(((io.wispforest.accessories.pond.AccessoriesRenderStateAPI) entityState).getEntityUUIDForState(), stack, renderer, e); } poseStack.popPose(); @@ -203,11 +203,11 @@ public static void submitFirstPerson(A e var entityState = avatarRender.createRenderState(entity, partialTicks); - entityState.setStateData(AccessoriesRenderStateKeys.LIGHT, combinedLight); + ((io.wispforest.accessories.pond.AccessoriesRenderStateAPImpl) entityState).setStateData(AccessoriesRenderStateKeys.LIGHT, combinedLight); AccessoriesRenderStateKeys.setupStateForAccessories(entityState, entity, partialTicks, arm); - var states = entityState.getStateData(AccessoriesRenderStateKeys.ACCESSORY_RENDER_STATES); + var states = ((io.wispforest.accessories.pond.AccessoriesRenderStateAPImpl) entityState).getStateData(AccessoriesRenderStateKeys.ACCESSORY_RENDER_STATES); if (states == null) return; @@ -220,7 +220,7 @@ public static void submitFirstPerson(A e try { renderer.render(accessoryRenderState, entityState, model, matrices, submitNodeCollector); } catch (Throwable e) { - AccessoryRendererErrorCache.logIfTimeAllotted(entityState.getEntityUUIDForState(), stack, renderer, e); + AccessoryRendererErrorCache.logIfTimeAllotted(((io.wispforest.accessories.pond.AccessoriesRenderStateAPI) entityState).getEntityUUIDForState(), stack, renderer, e); } matrices.popPose(); diff --git a/common/src/main/java/io/wispforest/accessories/client/AccessoryRendererErrorCache.java b/common/src/main/java/io/wispforest/accessories/client/AccessoryRendererErrorCache.java index d6092f0fa..00a6f3d0b 100644 --- a/common/src/main/java/io/wispforest/accessories/client/AccessoryRendererErrorCache.java +++ b/common/src/main/java/io/wispforest/accessories/client/AccessoryRendererErrorCache.java @@ -3,7 +3,7 @@ import com.mojang.logging.LogUtils; import io.wispforest.accessories.api.client.AccessoriesRendererRegistry; import io.wispforest.accessories.api.client.renderers.AccessoryRenderer; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.world.item.ItemStack; import org.slf4j.Logger; @@ -23,5 +23,5 @@ public static void logIfTimeAllotted(UUID uuid, ItemStack stack, AccessoryRender } } - public record Key(UUID entityUUID, int itemStackHash, ResourceLocation rendererId) { } + public record Key(UUID entityUUID, int itemStackHash, Identifier rendererId) { } } diff --git a/common/src/main/java/io/wispforest/accessories/client/BlitSpectrumRenderState.java b/common/src/main/java/io/wispforest/accessories/client/BlitSpectrumRenderState.java index 9cf02bc6f..7e46dcbc0 100644 --- a/common/src/main/java/io/wispforest/accessories/client/BlitSpectrumRenderState.java +++ b/common/src/main/java/io/wispforest/accessories/client/BlitSpectrumRenderState.java @@ -4,7 +4,7 @@ import com.mojang.blaze3d.vertex.VertexConsumer; import net.minecraft.client.gui.navigation.ScreenRectangle; import net.minecraft.client.gui.render.TextureSetup; -import net.minecraft.client.gui.render.state.GuiElementRenderState; +import net.minecraft.client.renderer.state.gui.GuiElementRenderState; import org.jetbrains.annotations.Nullable; import org.joml.Matrix3x2f; import org.joml.Vector4f; diff --git a/common/src/main/java/io/wispforest/accessories/client/DrawUtils.java b/common/src/main/java/io/wispforest/accessories/client/DrawUtils.java index e2121e36e..a80fee5a9 100644 --- a/common/src/main/java/io/wispforest/accessories/client/DrawUtils.java +++ b/common/src/main/java/io/wispforest/accessories/client/DrawUtils.java @@ -1,23 +1,24 @@ package io.wispforest.accessories.client; +import io.wispforest.accessories.pond.GuiGraphicsAccess; import io.wispforest.owo.ui.core.Color; -import io.wispforest.owo.ui.core.OwoUIDrawContext; +import io.wispforest.owo.ui.core.OwoUIGraphics; import io.wispforest.owo.ui.core.OwoUIPipelines; import io.wispforest.owo.ui.renderstate.GradientQuadElementRenderState; import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.gui.navigation.ScreenRectangle; import net.minecraft.client.gui.render.TextureSetup; import net.minecraft.client.renderer.RenderPipelines; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.data.AtlasIds; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import org.joml.Matrix3x2f; import org.joml.Vector4f; public class DrawUtils { - public static void drawWithSpectrum(GuiGraphics ctx, int x, int y, int blitOffset, int width, int height, ResourceLocation texture, float alpha) { + public static void drawWithSpectrum(GuiGraphicsExtractor ctx, int x, int y, int blitOffset, int width, int height, Identifier texture, float alpha) { TextureAtlasSprite sprite = Minecraft.getInstance().getAtlasManager() .getAtlasOrThrow(AtlasIds.GUI) .getSprite(texture); @@ -25,11 +26,11 @@ public static void drawWithSpectrum(GuiGraphics ctx, int x, int y, int blitOffse innerDrawWithSpectrum(ctx, sprite.atlasLocation(), x, x + width, y, y + height, blitOffset, sprite.getU0(), sprite.getU1(), sprite.getV0(), sprite.getV1(), new Vector4f(alpha)); } - public static void drawWithSpectrum(GuiGraphics ctx, int x, int y, int blitOffset, int width, int height, TextureAtlasSprite sprite, float alpha) { + public static void drawWithSpectrum(GuiGraphicsExtractor ctx, int x, int y, int blitOffset, int width, int height, TextureAtlasSprite sprite, float alpha) { innerDrawWithSpectrum(ctx, sprite.atlasLocation(), x, x + width, y, y + height, blitOffset, sprite.getU0(), sprite.getU1(), sprite.getV0(), sprite.getV1(), new Vector4f(alpha)); } - public static void drawWithSpectrum(GuiGraphics ctx, int x, int y, int blitOffset, int width, int height, TextureAtlasSprite sprite, Vector4f alphaValues) { + public static void drawWithSpectrum(GuiGraphicsExtractor ctx, int x, int y, int blitOffset, int width, int height, TextureAtlasSprite sprite, Vector4f alphaValues) { innerDrawWithSpectrum(ctx, sprite.atlasLocation(), x, x + width, y, y + height, blitOffset, sprite.getU0(), sprite.getU1(), sprite.getV0(), sprite.getV1(), alphaValues); } @@ -37,8 +38,9 @@ public static void drawWithSpectrum(GuiGraphics ctx, int x, int y, int blitOffse // Y: Top Right // Z: Bottom Left // W: Bottom Right - private static void innerDrawWithSpectrum(GuiGraphics guiGraphics, ResourceLocation atlasLocation, int x1, int x2, int y1, int y2, int blitOffset, float minU, float maxU, float minV, float maxV, Vector4f alphaValues) { - guiGraphics.guiRenderState.submitGuiElement( + private static void innerDrawWithSpectrum(GuiGraphicsExtractor guiGraphics, Identifier atlasLocation, int x1, int x2, int y1, int y2, int blitOffset, float minU, float maxU, float minV, float maxV, Vector4f alphaValues) { + var access = (GuiGraphicsAccess) (Object) guiGraphics; + access.accessories$guiRenderState().addGuiElement( new BlitSpectrumRenderState( AccessoriesPipelines.SPECTRUM, TextureSetup.noTexture(), @@ -47,12 +49,12 @@ private static void innerDrawWithSpectrum(GuiGraphics guiGraphics, ResourceLocat minU, maxU, minV, maxV, alphaValues, - guiGraphics.scissorStack.peek() + access.accessories$scissorStack().peek() ) ); } - public static void drawRectOutlineWithSpectrum(OwoUIDrawContext ctx, int x, int y, int width, int height, float alpha, boolean vertical) { + public static void drawRectOutlineWithSpectrum(OwoUIGraphics ctx, int x, int y, int width, int height, float alpha, boolean vertical) { innerFill(ctx, x, y, width, 1, alpha, !vertical); innerFill(ctx, x, y + height - 1, width, 1, alpha, !vertical); @@ -60,17 +62,18 @@ public static void drawRectOutlineWithSpectrum(OwoUIDrawContext ctx, int x, int innerFill(ctx, x + width - 1, y + 1, 1, height - 2, alpha, vertical); } - private static void innerFill(GuiGraphics guiGraphics, int x, int y, int width, int height, float alpha, boolean vertical) { + private static void innerFill(GuiGraphicsExtractor guiGraphics, int x, int y, int width, int height, float alpha, boolean vertical) { var multiplier = (float) ((System.currentTimeMillis() / 20d % 360d) / 360d); var topValue = 1f - multiplier; var bottomValue = topValue; //0f + multiplier; var matrix = new Matrix3x2f(guiGraphics.pose()); - var scissorRect = guiGraphics.scissorStack.peek(); + var gfxAccess = (GuiGraphicsAccess) (Object) guiGraphics; + var scissorRect = gfxAccess.accessories$scissorStack().peek(); - // TODO: SEEMS BROKEN WHEN ANYTHING IS MANIPULATION THE MATRIX STACK SOOOOOO - guiGraphics.guiRenderState.submitGuiElement( + // TODO: SEEMS BROKEN WHEN ANYTHING IS MANIPULATING THE MATRIX STACK SOOOOOO + gfxAccess.accessories$guiRenderState().addGuiElement( new GradientQuadElementRenderState( OwoUIPipelines.GUI_HSV, matrix, @@ -88,32 +91,32 @@ private static ScreenRectangle getBounds(int x1, int y1, int x2, int y2, Matrix3 return new ScreenRectangle(x1, y1, Math.abs(x2 - x1), Math.abs(y2 - y1))/*.transformMaxBounds(matrix3x2f)*/; } - public static void blitSprite(GuiGraphics context, ResourceLocation atlasLocation, int x, int y, int width, int height) { + public static void blitSprite(GuiGraphicsExtractor context, Identifier atlasLocation, int x, int y, int width, int height) { blitSprite(context, atlasLocation, x, y, width, height, -1); } - public static void blitSprite(GuiGraphics context, ResourceLocation atlasLocation, int x, int y, int width, int height, int blitOffset) { + public static void blitSprite(GuiGraphicsExtractor context, Identifier atlasLocation, int x, int y, int width, int height, int blitOffset) { context.blitSprite(RenderPipelines.GUI_TEXTURED, atlasLocation, x, y, width, height, blitOffset); } - public static void blit(GuiGraphics context, ResourceLocation atlasLocation, int x, int y, int width, int height) { + public static void blit(GuiGraphicsExtractor context, Identifier atlasLocation, int x, int y, int width, int height) { blit(context, atlasLocation, x, y, 0, 0, width, height, width, height); } - public static void blit(GuiGraphics context, ResourceLocation atlasLocation, int x, int y, int uWidth, int vHeight, int textureWidth, int textureHeight) { + public static void blit(GuiGraphicsExtractor context, Identifier atlasLocation, int x, int y, int uWidth, int vHeight, int textureWidth, int textureHeight) { blit(context, atlasLocation, x, y, 0, 0, uWidth, vHeight, textureWidth, textureHeight); } - public static void blit(GuiGraphics context, ResourceLocation atlasLocation, int x, int y, float uOffset, float vOffset, int uWidth, int vHeight, int textureWidth, int textureHeight) { + public static void blit(GuiGraphicsExtractor context, Identifier atlasLocation, int x, int y, float uOffset, float vOffset, int uWidth, int vHeight, int textureWidth, int textureHeight) { context.blit(RenderPipelines.GUI_TEXTURED, atlasLocation, x, y, uOffset, vOffset, uWidth, vHeight, uWidth, vHeight, textureWidth, textureHeight); } - public static void blit(GuiGraphics context, ResourceLocation atlasLocation, int x, int y, float uOffset, float vOffset, int uWidth, int vHeight, int width, int height, int textureWidth, int textureHeight) { + public static void blit(GuiGraphicsExtractor context, Identifier atlasLocation, int x, int y, float uOffset, float vOffset, int uWidth, int vHeight, int width, int height, int textureWidth, int textureHeight) { context.blit(RenderPipelines.GUI_TEXTURED, atlasLocation, x, y, uOffset, vOffset, uWidth, vHeight, width, height, textureWidth, textureHeight, -1); } // TODO: THIS CURRENTLY DOSE NOT MAKE THE ICONS WHITE AT ALL AND REQUIRES HEAVY MODIFICATION SIMILAR TO OWO BLUR TO SETUP THE UNIFORMS CORRECTLY - public static void blitSpriteWithColor(GuiGraphics context, TextureAtlasSprite sprite, int x, int y, int width, int height, Color color) { + public static void blitSpriteWithColor(GuiGraphicsExtractor context, TextureAtlasSprite sprite, int x, int y, int width, int height, Color color) { context.blitSprite(RenderPipelines.GUI_TEXTURED/*location -> AccessoriesPipelines.COLORED_GUI_TEXTURED.apply(color, location)*/, sprite, x, y, width, height, color.argb()); } } diff --git a/common/src/main/java/io/wispforest/accessories/client/MPOATVConstructingVertexConsumer.java b/common/src/main/java/io/wispforest/accessories/client/MPOATVConstructingVertexConsumer.java index 88e3cafa8..cced23c8b 100644 --- a/common/src/main/java/io/wispforest/accessories/client/MPOATVConstructingVertexConsumer.java +++ b/common/src/main/java/io/wispforest/accessories/client/MPOATVConstructingVertexConsumer.java @@ -46,9 +46,11 @@ public VertexConsumer addVertex(float x, float y, float z) { return this; } + @Override public VertexConsumer setColor(int color) { return this; } @Override public VertexConsumer setColor(int i, int j, int k, int l) { return this; } @Override public VertexConsumer setUv(float f, float g) { return this; } @Override public VertexConsumer setUv1(int i, int j) { return this; } @Override public VertexConsumer setUv2(int i, int j) { return this; } @Override public VertexConsumer setNormal(float f, float g, float h) { return this; } + @Override public VertexConsumer setLineWidth(float width) { return this; } } \ No newline at end of file diff --git a/common/src/main/java/io/wispforest/accessories/client/gui/AccessoriesScreen.java b/common/src/main/java/io/wispforest/accessories/client/gui/AccessoriesScreen.java index 015fb67d1..c8a983776 100644 --- a/common/src/main/java/io/wispforest/accessories/client/gui/AccessoriesScreen.java +++ b/common/src/main/java/io/wispforest/accessories/client/gui/AccessoriesScreen.java @@ -1,16 +1,22 @@ package io.wispforest.accessories.client.gui; -import com.mojang.logging.LogUtils; import io.wispforest.accessories.Accessories; +import io.wispforest.accessories.api.action.ActionResponseBuffer; +import io.wispforest.accessories.api.action.ValidationState; +import io.wispforest.accessories.api.client.tooltip.TooltipComponentBuilderImpl; +import io.wispforest.accessories.api.tooltip.*; import io.wispforest.accessories.api.client.screen.AccessoriesScreenTransitionHelper; import io.wispforest.accessories.api.menu.AccessoriesBasedSlot; import io.wispforest.accessories.api.slot.SlotGroup; import io.wispforest.accessories.api.slot.UniqueSlotHandling; +import io.wispforest.accessories.api.tooltip.impl.ListTooltipEntry; +import io.wispforest.accessories.api.tooltip.impl.TooltipEntry; import io.wispforest.accessories.client.AccessoriesClient; import io.wispforest.accessories.client.AccessoriesFunkyRenderingState; import io.wispforest.accessories.client.DrawUtils; import io.wispforest.accessories.client.gui.components.*; import io.wispforest.accessories.client.gui.utils.Line3d; +import io.wispforest.accessories.compat.config.TooltipInfoType; import io.wispforest.accessories.data.SlotGroupLoader; import io.wispforest.accessories.data.SlotTypeLoader; import io.wispforest.accessories.impl.option.PlayerOption; @@ -21,43 +27,55 @@ import io.wispforest.accessories.menu.SlotTypeAccessible; import io.wispforest.accessories.menu.networking.ToggledSlots; import io.wispforest.accessories.menu.variants.AccessoriesMenu; +import io.wispforest.accessories.mixin.client.AbstractContainerScreenAccessor; +import io.wispforest.accessories.mixin.client.GuiGraphicsAccessor; import io.wispforest.accessories.networking.AccessoriesNetworking; import io.wispforest.accessories.networking.holder.SyncOptionChange; import io.wispforest.accessories.pond.ContainerScreenExtension; +import io.wispforest.accessories.pond.DeferredTooltipGetter; +import io.wispforest.accessories.pond.TooltipFlagExtended; +import io.wispforest.accessories.utils.ComponentOps; import io.wispforest.owo.mixin.ui.SlotAccessor; -import io.wispforest.owo.ui.base.BaseOwoHandledScreen; +import io.wispforest.owo.ui.base.BaseOwoContainerScreen; import io.wispforest.owo.ui.component.ButtonComponent; -import io.wispforest.owo.ui.container.Containers; +import io.wispforest.owo.ui.container.UIContainers; import io.wispforest.owo.ui.container.FlowLayout; import io.wispforest.owo.ui.container.ScrollContainer; import io.wispforest.owo.ui.container.StackLayout; import io.wispforest.owo.ui.core.*; import io.wispforest.owo.util.pond.OwoSlotExtension; import it.unimi.dsi.fastutil.Pair; +import it.unimi.dsi.fastutil.booleans.BooleanUnaryOperator; import net.minecraft.ChatFormatting; import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.gui.screens.ErrorScreen; import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; +import net.minecraft.client.gui.screens.inventory.tooltip.DefaultTooltipPositioner; import net.minecraft.client.input.KeyEvent; -import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.RenderPipelines; +import net.minecraft.client.renderer.rendertype.RenderType; import net.minecraft.network.chat.Component; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.inventory.*; +import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.TooltipFlag; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.joml.Vector3d; import org.lwjgl.glfw.GLFW; -import org.slf4j.Logger; +import java.lang.ref.WeakReference; import java.util.*; +import java.util.function.BiConsumer; +import java.util.function.Consumer; +import java.util.function.UnaryOperator; import java.util.stream.Collectors; import java.util.stream.Stream; -public class AccessoriesScreen extends BaseOwoHandledScreen implements AccessoriesScreenBase, ContainerScreenExtension, PlayerOptionsAccess { +public class AccessoriesScreen extends BaseOwoContainerScreen implements AccessoriesScreenBase, ContainerScreenExtension, PlayerOptionsAccess { - private static final Logger LOGGER = LogUtils.getLogger(); private final @Nullable AbstractContainerScreen prevScreen; public AccessoriesScreen(AccessoriesMenu handler, Inventory inventory, Component title) { @@ -74,7 +92,7 @@ public AccessoriesScreen(AccessoriesMenu handler, Inventory inventory, Component @Override protected @NotNull OwoUIAdapter createAdapter() { - return OwoUIAdapter.create(this, Containers::verticalFlow); + return OwoUIAdapter.create(this, UIContainers::verticalFlow); } protected FlowLayout rootComponent() { @@ -90,7 +108,7 @@ public List getComponentRectangles() { var unpackRules = new ArrayDeque>>(); unpackRules.push(List.of()); - unpackRules.push(List.of(Pair.of(false, "armor_entity_layout"), Pair.of(true, "bottom_inventory_section"))); + unpackRules.push(List.of(Pair.of(false, ARMOR_ENTITY.id()), Pair.of(true, "bottom_inventory_section"))); unpackRules.push(List.of(Pair.of(false, "outer_accessories_layout"))); var stream = rootComponent().children().stream(); @@ -99,7 +117,7 @@ public List getComponentRectangles() { var ids = unpackRules.pollLast(); stream = stream.flatMap(component -> { - if (component instanceof ParentComponent parent) { + if (component instanceof ParentUIComponent parent) { if (ids.isEmpty()) return parent.children().stream(); if (parent.id() != null) { @@ -132,7 +150,7 @@ public List getComponentRectangles() { } @Override - public C component(Class expectedClass, String id) { + public C component(Class expectedClass, String id) { return super.component(expectedClass, id); } @@ -178,6 +196,8 @@ public void disableSlot(Slot slot) { hideSlot(index); this.changedSlots.put(index, true); + + currentEquipCheckStack = ItemStack.EMPTY; } @Override @@ -190,6 +210,8 @@ public void enableSlot(Slot slot) { if (!this.changedSlots.getOrDefault(index, true)) return; this.changedSlots.put(index, false); + + currentEquipCheckStack = ItemStack.EMPTY; } //-- @@ -275,71 +297,426 @@ protected boolean hasClickedOutside(double mouseX, double mouseY, int guiLeft, i return true; } - //-- + //-- Slot Darkening Logic -// @Override -// protected int getLayerZOffset(HandledScreenLayer layer) { -// if(layer == HandledScreenLayer.CURSOR_ITEM || layer == HandledScreenLayer.ITEM_TOOLTIP) { -// return 600; -// } -// -// return super.getLayerZOffset(layer); -// } + private ItemStack currentEquipCheckStack = ItemStack.EMPTY; + + private boolean isOutsideInvArea = false; + + private final Map slotToEquipCheck = new WeakHashMap<>(); + + private static class SlotEquipCheckerState { + public static final SlotEquipCheckerState EMPTY = new SlotEquipCheckerState(-1).isValid(true); + + private final int slotIndex; + private final AnimatableProperty color = AnimatableProperty.of(Color.ofArgb(0x00000000)); + + private boolean isValid = true; + private State state = State.Light; + + public SlotEquipCheckerState(Slot slot) { + this(slot.index); + } + + public SlotEquipCheckerState(int slotIndex) { + this.slotIndex = slotIndex; + } + + public SlotEquipCheckerState isValid(boolean value) { + isValid = value; + + return this; + } + + public boolean isValid() { + return isValid; + } + + public boolean isDarkened(Slot slot) { + return state != State.Light && !((OwoSlotExtension) slot).owo$getDisabledOverride(); + } + + public Color getColor() { + return color.get(); + } + + public void updateSlotDarkening(boolean isOutsideInvArea, boolean isHoveringASlot, @Nullable Slot hoveredSlot, boolean isCarryingStack, float partialTick) { + color.update(partialTick); + + if ((isOutsideInvArea && isCarryingStack) || (hoveredSlot != null && slotIndex == hoveredSlot.index)) { + if (isValid) { + startLightning(); + } else { + startDarkening(isHoveringASlot); + } + } else if (state.isDark()) { + startLightning(); + } + } + + private void startLightning() { + if (state.isLight()) return; + + color.animate(500, Easing.QUADRATIC, Color.ofArgb(0x00000000)) + .forwards() + .finished() + .subscribe((dir, looping) -> state = State.Light); + + state = State.Lightning; + } + + private void startDarkening(boolean fast) { + if (fast ? state.isFastDark() : state.isDark()) return; + + color.animate(fast ? 250 : 650, Easing.QUADRATIC, Color.ofArgb(0x4D000000)) + .forwards() + .finished() + .subscribe((dir, looping) -> state = State.Dark); + + state = fast ? State.FastDarkening : State.Darkening; + } + + public void render(GuiGraphicsExtractor guiGraphics, Slot slot, boolean isSideBySideSlots) { + int x = slot.x, y = slot.y; + + if (!isDarkened(slot)) return; + + var color = getColor().argb(); + + if (!(slot instanceof AccessoriesBasedSlot basedSlot) || (basedSlot.isCosmetic && isSideBySideSlots)) { + guiGraphics.fill(x, y, x + 16, y + 16, color); + } else { + guiGraphics.fill(x, y, x + 13, y + 2, color); + guiGraphics.fill(x, y + 2, x + 14, y + 16, color); + guiGraphics.fill(x + 14, y + 3, x + 16, y + 16, color); + } + } + + private enum State { + Darkening, + FastDarkening, + Dark, + Lightning, + Light; + + public boolean isDark() { return isFastDark() || this == State.Darkening; } + + public boolean isFastDark() { return this == State.FastDarkening || this == State.Dark; } + + public boolean isLight() { return this == State.Lightning || this == State.Light; } + } + } + + public void updateSlotDarkening(float partialTick) { + var isCarryingStack = !this.getMenu().getCarried().isEmpty(); + var isHoveringSlot = hoveredSlot instanceof SlotTypeAccessible; + + stateAccess.forEach((slot, state) -> { + state.updateSlotDarkening(isOutsideInvArea, isHoveringSlot, this.hoveredSlot, isCarryingStack, partialTick); + }); + } + + private interface SlotEquipStateAccess { + void forEach(BiConsumer consumer); + + SlotEquipCheckerState getOrDefault(Slot slot); + + SlotEquipCheckerState getOrCreate(Slot slot); + } + + private final SlotEquipStateAccess stateAccess = new SlotEquipStateAccess() { + @Override + public void forEach(BiConsumer consumer) { + if (!Accessories.config().screenOptions.showSlotDarkeningEffect()) return; + + AccessoriesScreen.this.slotToEquipCheck.forEach(consumer); + } + + @Override + public SlotEquipCheckerState getOrDefault(Slot slot) { + if (!Accessories.config().screenOptions.showSlotDarkeningEffect()) return SlotEquipCheckerState.EMPTY; + + return AccessoriesScreen.this.slotToEquipCheck.getOrDefault(slot, SlotEquipCheckerState.EMPTY); + } + + public SlotEquipCheckerState getOrCreate(Slot slot) { + if (!Accessories.config().screenOptions.showSlotDarkeningEffect()) return SlotEquipCheckerState.EMPTY; + + return AccessoriesScreen.this.slotToEquipCheck.computeIfAbsent(slot, SlotEquipCheckerState::new); + } + }; + + public SlotEquipStateAccess getSlotToEquipCheckMap(ItemStack stack) { + if (!ItemStack.matches(stack, currentEquipCheckStack) && Accessories.config().screenOptions.showSlotDarkeningEffect()) { + var player = Minecraft.getInstance().player; + + for (var slot : this.getMenu().slots) { + if (slot instanceof SlotTypeAccessible) { + slotToEquipCheck.computeIfAbsent(slot, SlotEquipCheckerState::new) + .isValid((stack.isEmpty() || slot.mayPlace(stack)) && slot.mayPickup(player)); + } + } + + currentEquipCheckStack = stack.copy(); + } + + return stateAccess; + } + + + protected void extractSlotHighlightBack(GuiGraphicsExtractor guiGraphics) { + var slotToEquipCheck = getSlotToEquipCheckMap(this.getMenu().getCarried()); + + if (this.hoveredSlot == null || !this.hoveredSlot.isHighlightable() || !slotToEquipCheck.getOrDefault(hoveredSlot).isValid()) { + return; + } + + var texture = AbstractContainerScreenAccessor.accessories$SLOT_HIGHLIGHT_BACK_SPRITE(); + int x = this.hoveredSlot.x - 4, y = this.hoveredSlot.y - 4; + + renderWithClippingCheck(guiGraphics, x, y, (graphics) -> graphics.blitSprite(RenderPipelines.GUI_TEXTURED, texture, x, y, 24, 24)); + } + + protected void extractSlotHighlightFront(GuiGraphicsExtractor guiGraphics) { + var access = getSlotToEquipCheckMap(this.getMenu().getCarried()); + + var isSideBySideSlots = this.getDefaultedData(PlayerOptions.SIDE_BY_SIDE_SLOTS); + + access.forEach((slot, data) -> data.render(guiGraphics, slot, isSideBySideSlots)); + + if (this.hoveredSlot == null || !this.hoveredSlot.isHighlightable()) return; + + var data = access.getOrCreate(this.hoveredSlot); + + if (this.currentEquipCheckStack.isEmpty()) data.isValid(this.hoveredSlot.mayPickup(Minecraft.getInstance().player)); + if (!data.isValid()) return; + + var texture = AbstractContainerScreenAccessor.accessories$SLOT_HIGHLIGHT_FRONT_SPRITE(); + int x = this.hoveredSlot.x - 4, y = this.hoveredSlot.y - 4; + + renderWithClippingCheck(guiGraphics, x, y, (graphics) -> graphics.blitSprite(RenderPipelines.GUI_TEXTURED, texture, x, y, 24, 24)); + } + + private void renderWithClippingCheck(GuiGraphicsExtractor guiGraphics, int x, int y, Consumer drawCall) { + if (!(hoveredSlot instanceof AccessoriesBasedSlot basedSlot) || (basedSlot.isCosmetic && this.getDefaultedData(PlayerOptions.SIDE_BY_SIDE_SLOTS))) { + drawCall.accept(guiGraphics); + + return; + } + + guiGraphics.enableScissor(x, y, x + 17, y + 6); + drawCall.accept(guiGraphics); + guiGraphics.disableScissor(); + + guiGraphics.enableScissor(x, y + 6, x + 18, y + 24); + drawCall.accept(guiGraphics); + guiGraphics.disableScissor(); + + guiGraphics.enableScissor(x + 18, y + 7, x + 24, y + 24); + drawCall.accept(guiGraphics); + guiGraphics.disableScissor(); + } + + //--- + + private TooltipCacheData tooltipStackKey = TooltipCacheData.EMPTY; + private final TooltipComponentBuilderImpl validationTooltipComponents = (TooltipComponentBuilderImpl) TooltipComponentBuilder.of(); @Override - protected void renderTooltip(GuiGraphics guiGraphics, int x, int y) { + protected void extractTooltip(GuiGraphicsExtractor guiGraphics, int x, int y) { + boolean bl = false; + if(this.hoveredSlot != null) { if (this.hoveredSlot instanceof AccessoriesBasedSlot accessoriesInternalSlot) { - if (!ArmorSlotTypes.isArmorType(accessoriesInternalSlot.slotName())) { - AccessoriesScreenBase.FORCE_TOOLTIP_LEFT.setValue(this.getDefaultedData(PlayerOptions.MAIN_WIDGET_POSITION)); - } + bl = !ArmorSlotTypes.isArmorType(accessoriesInternalSlot.slotName()) && this.getDefaultedData(PlayerOptions.MAIN_WIDGET_POSITION); } else if (this.hoveredSlot instanceof ArmorSlot) { - AccessoriesScreenBase.FORCE_TOOLTIP_LEFT.setValue(true); + bl = true; } else if (this.hoveredSlot.container instanceof TransientCraftingContainer || this.hoveredSlot instanceof ResultSlot) { - if (!(boolean) this.getDefaultedData(PlayerOptions.SHOW_GROUP_FILTER)) { - AccessoriesScreenBase.FORCE_TOOLTIP_LEFT.setValue(!(boolean) this.getDefaultedData(PlayerOptions.MAIN_WIDGET_POSITION)); - } + bl = !(boolean) this.getDefaultedData(PlayerOptions.SHOW_GROUP_FILTER) && !(boolean) this.getDefaultedData(PlayerOptions.MAIN_WIDGET_POSITION); } } - super.renderTooltip(guiGraphics, x, y); + AccessoriesScreenBase.setPositioner(bl); - AccessoriesScreenBase.FORCE_TOOLTIP_LEFT.setValue(false); - } + super.extractTooltip(guiGraphics, x, y); - @Override - protected List getTooltipFromContainerItem(ItemStack itemStack) { - var tooltipData = getTooltipFromItem(this.minecraft, itemStack); - - if (Accessories.config().screenOptions.showEquippedStackSlotType() - && this.menu.getCarried().isEmpty() - && this.hoveredSlot != null - && this.hoveredSlot.hasItem() - && this.hoveredSlot instanceof AccessoriesBasedSlot slot && ExtraSlotTypeProperties.getProperty(slot.slotName(), true).allowTooltipInfo()) { - var hoveredStack = this.hoveredSlot.getItem(); - - if (itemStack == hoveredStack) { - tooltipData.add(Component.empty()); - tooltipData.add( - Component.translatable(Accessories.translationKey("tooltip.currently_equipped_in")) + if (this.hoveredSlot instanceof AccessoriesBasedSlot slot && ExtraSlotTypeProperties.getProperty(slot.slotName(), true).allowTooltipInfo()) { + var client = Minecraft.getInstance(); + + var ctx = Item.TooltipContext.of(client.level); + var flag = TooltipFlagExtended.create(); + + var key = new TooltipCacheData(slot, this.getMenu().getCarried(), ((io.wispforest.accessories.pond.TooltipFlagExtended) flag).getModifiers()); + + var builder = TooltipComponentBuilder.of(); + var existingTooltip = ((DeferredTooltipGetter) guiGraphics).accessories$getTooltip(); + + if (existingTooltip != null) { + builder.add(existingTooltip); + } else { + builder.addAll(TooltipInfoProvider.gatherInfo(slot, TooltipEntry.of(), ctx, flag).entries()); + } + + if (this.menu.getCarried().isEmpty()) { + if (slot.hasItem() && Accessories.config().screenOptions.showEquippedStackSlotType()) { + builder + .divider(4) + .add( + Component.translatable(Accessories.translationKey("tooltip.currently_equipped_in")) .withStyle(ChatFormatting.GRAY) .append( - Component.translatable(slot.slotType().translation()) - .withStyle(ChatFormatting.BLUE) + Component.translatable(slot.slotType().translation()) + .withStyle(ChatFormatting.BLUE) ) + ); + } + } + + var tooltipType = Accessories.config().screenOptions.equipCheckTooltipType(); + + if (!key.equals(tooltipStackKey) && tooltipType != TooltipInfoType.DISABLED) { + tooltipStackKey = key; + validationTooltipComponents.clear(); + + if (!key.isEmpty()) { + var stackType = StackType.HELD; + var buffer = slot.checkInsertion(key.heldStack); + + if (buffer.isEmpty() || (buffer.canPerformAction().isValid() && !slot.getItem().isEmpty())) { + var otherBuffer = slot.checkExtraction(); + + if (buffer.isEmpty() || (!otherBuffer.isEmpty() && otherBuffer.canPerformAction() != ValidationState.VALID)){ + stackType = StackType.SLOT; + buffer = otherBuffer; + } + } + + if (!buffer.isEmpty()) { + addValidationInfo(buffer, tooltipType, stackType, validationTooltipComponents, ctx, flag); + } + } + } + + if (!validationTooltipComponents.isEmpty()) { + builder + .divider(4) + .add(validationTooltipComponents); + } + + if (!builder.isEmpty()) { + ((GuiGraphicsAccessor) guiGraphics).accessories$setTooltipForNextFrameInternal( + this.font, + ((TooltipComponentBuilderImpl) builder).build(TextWrapper.createWrapper(240)), + x, y, + DefaultTooltipPositioner.INSTANCE, + null, + true ); } } - return tooltipData; + AccessoriesScreenBase.setPositioner(false); + } + + private enum StackType { + HELD, + SLOT + } + + private static final class TooltipCacheData { + private static final TooltipCacheData EMPTY = new TooltipCacheData(null, ItemStack.EMPTY, 0); + + private final WeakReference slotRef; + private final ItemStack heldStack; + private final ItemStack slotStack; + private final int modifierBitmask; + + private TooltipCacheData(@Nullable AccessoriesBasedSlot slot, ItemStack heldStack, int modifierBitmask) { + this.slotRef = new WeakReference<>(slot); + this.heldStack = heldStack; + this.slotStack = slot != null ? slot.getItem() : ItemStack.EMPTY; + this.modifierBitmask = modifierBitmask; + } + + public boolean isEmpty() { + return heldStack.isEmpty() && slotStack.isEmpty(); + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof TooltipCacheData otherKey)) return false; + + return ItemStack.isSameItemSameComponents(this.heldStack, otherKey.heldStack) + && ItemStack.isSameItemSameComponents(this.slotStack, otherKey.slotStack) + && Objects.equals(this.slotRef.get(), otherKey.slotRef.get()) + && modifierBitmask == otherKey.modifierBitmask; + } + } + + private void addValidationInfo(ActionResponseBuffer buffer, TooltipInfoType tooltipType, StackType type, TooltipComponentBuilder builder, Item.TooltipContext ctx, TooltipFlag flag) { + if (tooltipType.equals(TooltipInfoType.ALL)) flag = ((io.wispforest.accessories.pond.TooltipFlagExtended) flag).withMask(Integer.MAX_VALUE); + + // TODO: SAVE TOOLTIP TO PREVENT REGATHERING INFO + var withSuccess = collectTooltipInfo(buffer, false, ctx, flag); + var withoutSuccess = collectTooltipInfo(buffer, true, ctx, flag); + + var splitData = (((io.wispforest.accessories.pond.TooltipFlagExtended) flag).hasShiftDown() || tooltipType.equals(TooltipInfoType.ADVANCED) ? withSuccess : withoutSuccess); + + var hasData = !splitData.isEmpty(); + + ComponentOps.ExtraInfoFooter footerGenerator; + + if (((io.wispforest.accessories.pond.TooltipFlagExtended) flag).getModifiers() != Integer.MAX_VALUE) { + var sizes = new HashSet<>(List.of(collectTooltipInfo(buffer, false, ctx, ((io.wispforest.accessories.pond.TooltipFlagExtended) flag).withMask(0)).hashCode())); + + footerGenerator = ComponentOps.attemptToAddExtraInfoFooter( + new LinkedHashSet<>(splitData.hashCode() != withSuccess.hashCode() ? List.of("key.keyboard.left.shift") : List.of()), + flag, + newFlag -> { + return sizes.add(collectTooltipInfo(buffer, false, ctx, newFlag).hashCode()); + } + ); + } else { + footerGenerator = new ComponentOps.ExtraInfoFooter(new LinkedHashMap<>()); + } + + if (hasData) { + builder + .add(Accessories.translation("tooltip", (type == StackType.HELD ? "accessory_reasoning" : "equipment_reasoning"))) + .divider(2) + .addAll(TextPrefixer.NONE, splitData); + + if (!footerGenerator.keyToFormattedText().isEmpty()) { + builder.divider(4); + } + } + + footerGenerator.addTo(builder); + } + + private ListTooltipAdder collectTooltipInfo(ActionResponseBuffer buffer, boolean filterSuccess, Item.TooltipContext ctx, TooltipFlag flag) { + var responses = buffer.responses(filterSuccess); + var adder = ListTooltipEntry.flatMap(); + + if (!responses.isEmpty()) { + for (var response : responses) { + var entryAdder = adder.createListedEntry( + response.canPerformAction().asEntryComponent(), + Accessories.translation("tooltip.equipment_reasoning.indent_entry")); + + TooltipInfoProvider.gatherInfo(response, entryAdder, ctx, flag); + } + } + + return adder; } private final List hoveredAccessoryPositons = new ArrayList<>(); private final List linesToAccessoryPositions = new ArrayList<>(); @Override - protected void renderBg(GuiGraphics guiGraphics, float partialTick, int mouseX, int mouseY) { - super.renderBg(guiGraphics, partialTick, mouseX, mouseY); + public void extractBackground(GuiGraphicsExtractor guiGraphics, int mouseX, int mouseY, float partialTick) { + super.extractBackground(guiGraphics, mouseX, mouseY, partialTick); //-- @@ -363,10 +740,12 @@ protected void renderBg(GuiGraphics guiGraphics, float partialTick, int mouseX, } @Override - public void render(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTick) { - this.renderBg(guiGraphics, partialTick, mouseX, mouseY); + public void extractRenderState(GuiGraphicsExtractor guiGraphics, int mouseX, int mouseY, float partialTick) { + updateSlotDarkening(partialTick); - super.render(guiGraphics, mouseX, mouseY, partialTick); + this.extractBackground(guiGraphics, mouseX, mouseY, partialTick); + + super.extractRenderState(guiGraphics, mouseX, mouseY, partialTick); if (Accessories.config().screenOptions.hoveredOptions.clickbait()) { hoveredAccessoryPositons.forEach(pos -> { @@ -417,7 +796,8 @@ public void render(GuiGraphics guiGraphics, int mouseX, int mouseY, float partia // } // }); - minecraft.renderBuffers().bufferSource().endBatch(RenderType.LINES); + // TODO: Port line rendering to new 1.21.11 rendering API (code above is commented) + minecraft.renderBuffers().bufferSource().endBatch(); linesToAccessoryPositions.clear(); } @@ -425,15 +805,15 @@ public void render(GuiGraphics guiGraphics, int mouseX, int mouseY, float partia //-- - public void showCosmeticState(boolean value) { - this.setData(PlayerOptions.SHOW_COSMETIC_SLOTS, value); + public static final ComponentKey ARMOR_ENTITY = ComponentKey.of(FlowLayout.class, "armor_entity_layout"); + public static final ComponentKey SIDE_BAR = ComponentKey.of(FlowLayout.class, "side_bar_holder"); + public static final ComponentKey TOGGLE_PANEL = ComponentKey.of(FlowLayout.class, "accessories_toggle_panel"); - AccessoriesNetworking.sendToServer(PlayerOptions.SHOW_COSMETIC_SLOTS.toPacket(value)); - } - - public boolean showCosmeticState() { - return this.getDefaultedData(PlayerOptions.SHOW_COSMETIC_SLOTS); - } + public static final ComponentKey GROUP_FILTER = ComponentKey.of(FlowLayout.class, "group_filter_holder"); + public static final ComponentKey BOTTOM_HOLDER = ComponentKey.of(FlowLayout.class, "bottom_component_holder"); + public static final ComponentKey CRAFTING_GRID = ComponentKey.of(FlowLayout.class, "crafting_grid_layout"); + public static final ComponentKey CRAFTING_GRID_BTN = ComponentKey.of(io.wispforest.owo.ui.core.UIComponent.class, "crafting_grid_btn"); + public static final ComponentKey ENTITY_PANEL = ComponentKey.of(StackLayout.class, "entity_button_panel"); @Override protected void build(FlowLayout rootComponent) { @@ -448,7 +828,7 @@ protected void build(FlowLayout rootComponent) { .verticalAlignment(VerticalAlignment.CENTER) .surface(Surface.VANILLA_TRANSLUCENT); - var baseChildren = new ArrayList(); + var baseChildren = new ArrayList(); var accessoriesComponent = createAccessoriesComponent(); @@ -470,79 +850,87 @@ protected void build(FlowLayout rootComponent) { this.enableSlot(offHandIndex); - var offhandComponent = Containers.verticalFlow(Sizing.content(), Sizing.content()) + var offhandComponent = UIContainers.verticalFlow(Sizing.content(), Sizing.content()) .child(this.slotAsComponent(offHandIndex).margins(Insets.of(1))) .padding(Insets.of(7, 7, 7, 4)) .allowOverflow(true); + var craftingGridArea = CRAFTING_GRID.withId( + UIContainers.verticalFlow(Sizing.content(), Sizing.content()) + .positioning(Positioning.absolute(162, -7)) + .configure((FlowLayout component) -> { + if (this.getDefaultedData(PlayerOptions.SHOW_CRAFTING_GRID)) { + component.child(createCraftingGrid()); + } + }) + ); + var bottomInvComponent = new FlowLayout(Sizing.content(), Sizing.content(), FlowLayout.Algorithm.HORIZONTAL){ @Override public boolean isInBoundingBox(double x, double y) { - return super.isInBoundingBox(x, y) - || offhandComponent.isInBoundingBox(x, y); + if (super.isInBoundingBox(x, y) || offhandComponent.isInBoundingBox(x, y)) return true; + + if (!craftingGridArea.children().isEmpty()) { + return craftingGridArea.children().getFirst().isInBoundingBox(x, y); + } + + return false; } - } - .child( - Containers.verticalFlow(Sizing.content(), Sizing.content()) // Sizing.expand() - .child(offhandComponent) - .allowOverflow(true) - .positioning(Positioning.absolute(-(18 + 4 + 7), 51)) -// .margins(Insets.top(54 + 4)) - ) - .child( - Containers.verticalFlow(Sizing.fixed(162), Sizing.fixed(76)) - .child(playerInv) -// .margins(Insets.left(4)) - .id("bottom_component_holder") - ) - .child( - Containers.verticalFlow(Sizing.content(), Sizing.content()) - .positioning(Positioning.absolute(162, -7)) - .configure((FlowLayout component) -> { - if (this.getDefaultedData(PlayerOptions.SHOW_CRAFTING_GRID)) { - component.child(createCraftingGrid()); - } - }) - .id("crafting_grid_layout") - ) - .padding(Insets.of(7)/*.add(0,0,0,22)*/) - .surface((ctx, component) -> { + + @Override + protected void parentUpdate(float delta, int mouseX, int mouseY) { + AccessoriesScreen.this.isOutsideInvArea = !isInBoundingBox(mouseX, mouseY); + } + }.child( + UIContainers.verticalFlow(Sizing.content(), Sizing.content()) + .child(offhandComponent) + .allowOverflow(true) + .positioning(Positioning.absolute(-(18 + 4 + 7), 51)) + ) + .child( + UIContainers.verticalFlow(Sizing.fixed(162), Sizing.fixed(76)) + .child(playerInv) + .id("bottom_component_holder") + ) + .child(craftingGridArea) + .padding(Insets.of(7)) + .surface((ctx, component) -> { // ComponentUtils.getPanelSurface().draw(ctx, component); // ComponentUtils.BACKGROUND_SLOT_RENDERING_SURFACE.draw(ctx, component); - var showCraftingGrid = this.getDefaultedData(PlayerOptions.SHOW_CRAFTING_GRID); - var width = showCraftingGrid ? 238 : 198; + var showCraftingGrid = this.getDefaultedData(PlayerOptions.SHOW_CRAFTING_GRID); + var width = showCraftingGrid ? 238 : 198; - DrawUtils.blit( - ctx, - Accessories.of("textures/gui/theme/" + ComponentUtils.checkMode("light", "dark") + "/player_inv/" + (showCraftingGrid ? "with" : "without") + "_crafting.png"), - component.x() - (18 + 4), component.y(), width, 90 - ); - }) - .allowOverflow(true) - .id("bottom_inventory_section"); + DrawUtils.blit( + ctx, + Accessories.of("textures/gui/theme/" + ComponentUtils.checkMode("light", "dark") + "/player_inv/" + (showCraftingGrid ? "with" : "without") + "_crafting.png"), + component.x() - (18 + 4), component.y(), width, 90 + ); + }) + .allowOverflow(true) + .id("bottom_inventory_section"); baseChildren.add(bottomInvComponent); //-- - var primaryLayout = (FlowLayout) Containers.horizontalFlow(Sizing.content(), Sizing.fixed(140)) + var primaryLayout = (FlowLayout) UIContainers.horizontalFlow(Sizing.content(), Sizing.fixed(140)) .gap(2) .horizontalAlignment(HorizontalAlignment.CENTER) .id("armor_entity_layout"); { - var armorSlotsLayout = Containers.verticalFlow(Sizing.content(), Sizing.content()) + var armorSlotsLayout = UIContainers.verticalFlow(Sizing.content(), Sizing.content()) .configure((FlowLayout layout) -> layout.allowOverflow(true)); - var outerLeftArmorLayout = Containers.horizontalFlow(Sizing.content(), Sizing.content()) + var outerLeftArmorLayout = UIContainers.horizontalFlow(Sizing.content(), Sizing.content()) .child(armorSlotsLayout); - var cosmeticArmorSlotsLayout = Containers.verticalFlow(Sizing.content(), Sizing.content()) + var cosmeticArmorSlotsLayout = UIContainers.verticalFlow(Sizing.content(), Sizing.content()) .configure((FlowLayout layout) -> layout.allowOverflow(true)); - var outerRightArmorLayout = Containers.horizontalFlow(Sizing.content(), Sizing.content()) + var outerRightArmorLayout = UIContainers.horizontalFlow(Sizing.content(), Sizing.content()) .child(cosmeticArmorSlotsLayout); for (int i = 0; i < menu.addedArmorSlots() / 2; i++) { @@ -558,9 +946,9 @@ public boolean isInBoundingBox(double x, double y) { //-- - var entityContainer = Containers.stack(Sizing.content(), Sizing.fixed(126 + 14)) + var entityContainer = UIContainers.stack(Sizing.content(), Sizing.fixed(126 + 14)) .child( - Containers.verticalFlow(Sizing.content(), Sizing.content()) + UIContainers.verticalFlow(Sizing.content(), Sizing.content()) .child( createEntityComponent() ).surface((ctx, component) -> { @@ -575,7 +963,7 @@ public boolean isInBoundingBox(double x, double y) { .id("entity_renderer_holder") ) .child( - Containers.verticalFlow(Sizing.fixed(0), Sizing.fixed(0)) + UIContainers.verticalFlow(Sizing.fixed(0), Sizing.fixed(0)) .surface((ctx, component) -> { // TODO: MAKE NO EQUIPMENT SLOT VARIANT... var surfaceType = Math.max(1, Math.min((this.getMenu().addedArmorSlots() / 2), 4)) + "_slots"; @@ -639,18 +1027,17 @@ public boolean isInBoundingBox(double x, double y) { }).positioning(Positioning.relative(100, 0)) ).child( ComponentUtils.createIconButton( - btn -> { - toggleAdvancedOptions(btn); - }, - 14, - "advanced_options_btn", - btn -> { - btn.tooltip(createToggleText("advanced_options", true, this.getDefaultedData(PlayerOptions.ADVANCED_SETTINGS))) - .margins(Insets.of(0, 3, 0, 3)); - }, - (ctx, btn) -> { - return Accessories.of("textures/gui/settings_icon" + (btn.isHovered() ? "_hovered" : "") + ".png"); - }).positioning(Positioning.relative(100, 100)) + this::toggleAdvancedOptions, + 14, + "advanced_options_btn", + btn -> { + btn.tooltip(createToggleText("advanced_options", true, this.getDefaultedData(PlayerOptions.ADVANCED_SETTINGS))) + .margins(Insets.of(0, 3, 0, 3)); + }, + (ctx, btn) -> { + return Accessories.of("textures/gui/settings_icon" + (btn.isHovered() ? "_hovered" : "") + ".png"); + } + ).positioning(Positioning.relative(100, 100)) ); if(!Accessories.config().screenOptions.alwaysShowCraftingGrid()){ @@ -660,10 +1047,11 @@ public boolean isInBoundingBox(double x, double y) { } primaryLayout.child( - entityContainer - .allowOverflow(true) - .padding(Insets.of(7)) - .id("entity_button_panel") + ENTITY_PANEL.withId( + entityContainer + .allowOverflow(true) + .padding(Insets.of(7)) + ) ); } @@ -693,7 +1081,7 @@ public boolean isInBoundingBox(double x, double y) { //-- - var baseLayout = Containers.verticalFlow(Sizing.content(), Sizing.content()) + var baseLayout = UIContainers.verticalFlow(Sizing.content(), Sizing.content()) .gap(2) .children(baseChildren.reversed()) .allowOverflow(true); @@ -710,13 +1098,13 @@ public boolean isInBoundingBox(double x, double y) { public void setupPadding() { if (this.topComponent == null) return; - var hasSideBar = this.rootComponent().childById(io.wispforest.owo.ui.core.Component.class, "side_bar_holder") != null; + var hasSideBar = this.rootComponent().childById(io.wispforest.owo.ui.core.UIComponent.class, "side_bar_holder") != null; var primaryLayout = rootComponent().childById(FlowLayout.class, "armor_entity_layout"); setupPadding(this.topComponent, hasSideBar, primaryLayout); } - public void setupPadding(AccessoriesContainingLayout accessoriesComponent, boolean hasSideBar, ParentComponent primaryLayout) { + public void setupPadding(AccessoriesContainingLayout accessoriesComponent, boolean hasSideBar, ParentUIComponent primaryLayout) { if (this.getDefaultedData(PlayerOptions.ENTITY_CENTERED)) { // (((Accessories Component Width) + 3) | 0) + (120) + ((3 + (30)) | 0 var padding = 0; @@ -732,7 +1120,7 @@ public void setupPadding(AccessoriesContainingLayout accessoriesComponent, bo if (this.getDefaultedData(PlayerOptions.SIDE_WIDGET_POSITION)) { roundingOffset = (this.getDefaultedData(PlayerOptions.MAIN_WIDGET_POSITION) ? -1 : -3); - } else if(component(io.wispforest.owo.ui.core.Component.class, "group_filter_holder") == null && !this.getDefaultedData(PlayerOptions.MAIN_WIDGET_POSITION)) { + } else if(component(io.wispforest.owo.ui.core.UIComponent.class, "group_filter_holder") == null && !this.getDefaultedData(PlayerOptions.MAIN_WIDGET_POSITION)) { roundingOffset = -2; } @@ -762,7 +1150,7 @@ public void rebuildEntityComponent() { rebuildComponentRectangles = true; } - public io.wispforest.owo.ui.core.Component createEntityComponent() { + public io.wispforest.owo.ui.core.UIComponent createEntityComponent() { var sideBySideView = this.getDefaultedData(PlayerOptions.SIDE_BY_SIDE_ENTITY); return InventoryEntityComponent.of(Sizing.fixed(sideBySideView ? 162 : 108), Sizing.fixed(126), this.getMenu().targetEntityDefaulted()) @@ -798,7 +1186,7 @@ public void rebuildAccessoriesComponent() { this.getMenu().getAccessoriesSlots().forEach(this::disableSlot); - var primaryLayout = rootComponent().childById(FlowLayout.class, "armor_entity_layout"); + var primaryLayout = ARMOR_ENTITY.getFrom(rootComponent()); //-- @@ -828,7 +1216,7 @@ public void rebuildAccessoriesComponent() { hasSideBar = swapOrCreateSideBarComponent(); } else { if(this.getMenu().selectedGroups().isEmpty()) { - var sideBarOptionsComponent = primaryLayout.childById(io.wispforest.owo.ui.core.Component.class, "accessories_toggle_panel"); + var sideBarOptionsComponent = primaryLayout.childById(io.wispforest.owo.ui.core.UIComponent.class, "accessories_toggle_panel"); if (sideBarOptionsComponent != null) { var sideParParent = sideBarOptionsComponent.parent(); @@ -850,26 +1238,23 @@ public void rebuildAccessoriesComponent() { public boolean swapOrCreateSideBarComponent() { if (this.topComponent == null && this.getMenu().selectedGroups().isEmpty()) return false; - var armorAndEntityComp = rootComponent().childById(FlowLayout.class, "armor_entity_layout"); + var armorAndEntityComp = ARMOR_ENTITY.getFrom(rootComponent()); - armorAndEntityComp.removeChild(armorAndEntityComp.childById(FlowLayout.class, "side_bar_holder")); + SIDE_BAR.removeFrom(armorAndEntityComp); var sideBarResultWidget = createSideBarOptions(); rebuildComponentRectangles = true; - if (sideBarResultWidget != null) { - if ((boolean) this.getDefaultedData(PlayerOptions.SIDE_WIDGET_POSITION) == this.getDefaultedData(PlayerOptions.MAIN_WIDGET_POSITION)) { - armorAndEntityComp.child(0, sideBarResultWidget); - } else { - armorAndEntityComp.child(sideBarResultWidget); - } + if (sideBarResultWidget == null) return false; - return true; + if ((boolean) this.getDefaultedData(PlayerOptions.SIDE_WIDGET_POSITION) == this.getDefaultedData(PlayerOptions.MAIN_WIDGET_POSITION)) { + armorAndEntityComp.child(0, sideBarResultWidget); + } else { + armorAndEntityComp.child(sideBarResultWidget); } - - return false; + return true; } @Nullable @@ -883,33 +1268,31 @@ private AccessoriesContainingLayout createAccessoriesComponent() { //-- @Nullable - private io.wispforest.owo.ui.core.Component createSideBarOptions() { - var accessoriesTogglePanel = (FlowLayout) Containers.verticalFlow(Sizing.content(), Sizing.content()) - .id("accessories_toggle_panel"); - + private io.wispforest.owo.ui.core.UIComponent createSideBarOptions() { var groupFilterComponent = createGroupFilters(); - if(groupFilterComponent != null) { - return Containers.verticalFlow(Sizing.content(), Sizing.content()) - .child( - accessoriesTogglePanel.child(groupFilterComponent) - .padding(Insets.of(7)) - .surface((ctx, component) -> { - ComponentUtils.getPanelSurface().and(ComponentUtils.getPanelWithInset(6)) - .draw(ctx, component); - }) - .horizontalAlignment(HorizontalAlignment.CENTER) - ) - .horizontalAlignment(this.getDefaultedData(PlayerOptions.MAIN_WIDGET_POSITION) ? HorizontalAlignment.LEFT : HorizontalAlignment.RIGHT) - .id("side_bar_holder"); - } + if (groupFilterComponent == null) return null; - return null; + var accessoriesTogglePanel = (FlowLayout) UIContainers.verticalFlow(Sizing.content(), Sizing.content()) + .id("accessories_toggle_panel"); + + return UIContainers.verticalFlow(Sizing.content(), Sizing.content()) + .child( + accessoriesTogglePanel.child(groupFilterComponent) + .padding(Insets.of(7)) + .surface((ctx, component) -> { + ComponentUtils.getPanelSurface().and(ComponentUtils.getPanelWithInset(6)) + .draw(ctx, component); + }) + .horizontalAlignment(HorizontalAlignment.CENTER) + ) + .horizontalAlignment(this.getDefaultedData(PlayerOptions.MAIN_WIDGET_POSITION) ? HorizontalAlignment.LEFT : HorizontalAlignment.RIGHT) + .id("side_bar_holder"); } public void rebuildSideBarOptions() { if(this.getDefaultedData(PlayerOptions.SHOW_GROUP_FILTER)) { - var panel = rootComponent().childById(FlowLayout.class, "accessories_toggle_panel"); + var panel = TOGGLE_PANEL.getFrom(rootComponent()); if(panel != null) { var groupFilter = this.createGroupFilters(); @@ -917,7 +1300,7 @@ public void rebuildSideBarOptions() { if (groupFilter != null) panel.child(groupFilter); } } else { - var component = rootComponent().childById(ParentComponent.class, "group_filter_holder"); + var component = rootComponent().childById(ParentUIComponent.class, "group_filter_holder"); if (component != null) component.remove(); } @@ -931,38 +1314,31 @@ public void rebuildSideBarOptions() { private ExtendedScrollContainer groupFilterScrollable = null; @Nullable - private io.wispforest.owo.ui.core.Component createGroupFilters() { + private io.wispforest.owo.ui.core.UIComponent createGroupFilters() { if (!this.getDefaultedData(PlayerOptions.SHOW_GROUP_FILTER)) return null; - var groups = new ArrayList<>(SlotGroupLoader.getValidGroups(this.getMenu().targetEntityDefaulted()).keySet()); + var capability = ((io.wispforest.accessories.pond.AccessoriesAPIAccess) this.targetEntityDefaulted()).accessoriesCapability(); + if (capability == null) return null; + var groups = new ArrayList<>(SlotGroupLoader.getValidGroups(this.getMenu().targetEntityDefaulted()).keySet()); if (groups.isEmpty()) return null; var usedSlots = this.getMenu().getUsedSlots(); - var groupButtons = new ArrayList(); + var groupButtons = new ArrayList(); - for (SlotGroup group : groups) { + // Filter Groups that have valid slots for the given target entity and are not from the unique slot API + for (var group : groups) { var groupSlots = group.slots().stream() - .filter(slotName -> { - if (UniqueSlotHandling.isUniqueSlot(slotName)) return false; - - var slotType = SlotTypeLoader.getSlotType(this.targetEntityDefaulted(), slotName); - - if (slotType == null) return false; - - var capability = this.targetEntityDefaulted().accessoriesCapability(); + .filter(slotName -> { + if (UniqueSlotHandling.isUniqueSlot(slotName)) return false; - if (capability == null) return false; + var container = capability.getContainers().get(slotName); - var container = capability.getContainer(slotType); - - if (container == null) return false; - - return container.getSize() > 0; - }) - .map((slotName) -> SlotTypeLoader.INSTANCE.getSlotType(false, slotName)) - .collect(Collectors.toSet()); + return container != null && container.getSize() > 0; + }) + .map((slotName) -> SlotTypeLoader.INSTANCE.getSlotType(false, slotName)) + .collect(Collectors.toSet()); if (groupSlots.isEmpty() || (usedSlots != null && groupSlots.stream().noneMatch(usedSlots::contains))) continue; @@ -971,53 +1347,52 @@ private io.wispforest.owo.ui.core.Component createGroupFilters() { if (groupButtons.isEmpty()) return null; - var baseButtonLayout = (ParentComponent) Containers.verticalFlow(Sizing.content(), Sizing.content()) + var baseButtonLayout = (ParentUIComponent) UIContainers.verticalFlow(Sizing.content(), Sizing.content()) .children(groupButtons) .gap(1); if(groupButtons.size() > 7) { - var scrollable = new ExtendedScrollContainer<>( - ScrollContainer.ScrollDirection.VERTICAL, - Sizing.fixed(18 + 3), - Sizing.fixed(108/*(5 * 14) + (5) + (2 * 2) - 1*/), - baseButtonLayout.padding(Insets.of(1)) + this.groupFilterScrollable = new ExtendedScrollContainer<>( + ScrollContainer.ScrollDirection.VERTICAL, + Sizing.fixed(18 + 3), + Sizing.fixed(108), + baseButtonLayout.padding(Insets.of(1)) ).configure((ExtendedScrollContainer scrollContainer) -> { scrollContainer.oppositeScrollbar((boolean) this.getDefaultedData(PlayerOptions.SIDE_WIDGET_POSITION) == this.getDefaultedData(PlayerOptions.MAIN_WIDGET_POSITION)) -// .customClippingInsets(Insets.of(1)) - .scrollToAfterLayout(groupFilterScrollable != null ? groupFilterScrollable.getProgress() : 0) - .scrollbarThiccness(2) - .scrollbar(ScrollContainer.Scrollbar.flat(Color.ofArgb(0xA0000000))) - .fixedScrollbarLength(16) - .padding(Insets.of(1, 2, 2, 1)) - .id("group_filters_scrollable"); + .scrollToAfterLayout(groupFilterScrollable != null ? groupFilterScrollable.getProgress() : 0) + .scrollbarThiccness(2) + .scrollbar(ScrollContainer.Scrollbar.flat(Color.ofArgb(0xA0000000))) + .fixedScrollbarLength(16) + .padding(Insets.of(1, 2, 2, 1)) + .id("group_filters_scrollable"); }); - baseButtonLayout = scrollable; - this.groupFilterScrollable = scrollable; + baseButtonLayout = this.groupFilterScrollable; } else { - baseButtonLayout.padding(Insets.of(1, 2, 2, 2)); this.groupFilterScrollable = null; + baseButtonLayout.padding(Insets.of(1, 2, 2, 2)); } - return Containers.verticalFlow(Sizing.content(), Sizing.content()) + var groupFilterHolder = UIContainers.verticalFlow(Sizing.content(), Sizing.content()); + groupFilterHolder.id("group_filter_holder"); + return groupFilterHolder .child( - ComponentUtils.createIconButton( - (btn) -> { - this.getMenu().selectedGroups().clear(); - this.rebuildAccessoriesComponent(); - }, - 14, - (btn) -> { - btn.tooltip(Component.translatable(Accessories.translationKey("reset.group_filter"))); - }, - (btn) -> { - return Accessories.of("textures/gui/reset_icon" + (btn.isHovered() ? "_hovered" : "") + ".png"); - }) - .margins(Insets.of(3, 1, 0, 0)) + ComponentUtils.createIconButton( + (btn) -> { + this.getMenu().selectedGroups().clear(); + this.rebuildAccessoriesComponent(); + }, + 14, + (btn) -> { + btn.tooltip(Component.translatable(Accessories.translationKey("reset.group_filter"))); + }, + (btn) -> { + return Accessories.of("textures/gui/reset_icon" + (btn.isHovered() ? "_hovered" : "") + ".png"); + }) + .margins(Insets.of(3, 1, 0, 0)) ) .child(baseButtonLayout) - .horizontalAlignment(HorizontalAlignment.CENTER) - .id("group_filter_holder"); + .horizontalAlignment(HorizontalAlignment.CENTER); } //-- @@ -1026,7 +1401,7 @@ private io.wispforest.owo.ui.core.Component createGroupFilters() { private AccessoriesScreenSettingsLayout settingsLayout = null; private void swapBottomComponentHolder() { - var holder = rootComponent().childById(FlowLayout.class, "bottom_component_holder"); + var holder = BOTTOM_HOLDER.getFrom(rootComponent()); holder.clearChildren(); @@ -1061,48 +1436,40 @@ private void swapBottomComponentHolder() { private void toggleCraftingGrid() { rebuildComponentRectangles = true; - this.removeCraftingGrid(); + var gridHolder = CRAFTING_GRID.getFrom(rootComponent()); - if (!(boolean) this.getDefaultedData(PlayerOptions.SHOW_CRAFTING_GRID)) return; + if (gridHolder == null) throw new IllegalStateException("Unable to get crafting grid layout!"); - var bottom_holder = rootComponent().childById(FlowLayout.class, "crafting_grid_layout");//side_bar_holder - - bottom_holder.child(createCraftingGrid()); - } + gridHolder.clearChildren(); - private void removeCraftingGrid() { - var bottom_holder = rootComponent().childById(FlowLayout.class, "crafting_grid_layout");//side_bar_holder + if (!this.getDefaultedData(PlayerOptions.SHOW_CRAFTING_GRID)) { + gridHolder.margins(Insets.of(0)); - if (bottom_holder != null) { - bottom_holder.clearChildren(); + for (int i = 0; i < 5; i++) this.disableSlot(i); } - if (!(boolean) this.getDefaultedData(PlayerOptions.SHOW_CRAFTING_GRID)) { - bottom_holder.margins(Insets.of(0)); + if (!this.getDefaultedData(PlayerOptions.SHOW_CRAFTING_GRID)) return; - for (int i = 0; i < 5; i++) this.disableSlot(i); - } + gridHolder.child(createCraftingGrid()); } - private io.wispforest.owo.ui.core.Component createCraftingGrid() { + private io.wispforest.owo.ui.core.UIComponent createCraftingGrid() { return ComponentUtils.createCraftingComponent(0, this::slotAsComponent, this::enableSlot, true) .id("crafting_component"); } - private io.wispforest.owo.ui.core.Component createCraftingToggleButton() { + private io.wispforest.owo.ui.core.UIComponent createCraftingToggleButton() { return ComponentUtils.createIconButton( btn -> { AccessoriesNetworking .sendToServer(SyncOptionChange.of(PlayerOptions.SHOW_CRAFTING_GRID, this.menu.owner(), bl -> !bl)); - this.setData(PlayerOptions.SHOW_CRAFTING_GRID, !this.getDefaultedData(PlayerOptions.SHOW_CRAFTING_GRID)); - - btn.tooltip(createToggleText("crafting_grid", true, this.getDefaultedData(PlayerOptions.SHOW_CRAFTING_GRID))); + btn.tooltip(createToggleText("crafting_grid", true, this.setDataFrom(PlayerOptions.SHOW_CRAFTING_GRID, BooleanUnaryOperator.negation()))); this.toggleCraftingGrid(); }, 14, - "crafting_grid_btn", + CRAFTING_GRID_BTN.id(), btn -> { btn.tooltip(createToggleText("crafting_grid", true, this.getDefaultedData(PlayerOptions.SHOW_CRAFTING_GRID))) .margins(Insets.of(0, 3, 3, 0)); @@ -1120,24 +1487,20 @@ public void onHolderChange(PlayerOption option) { settingsLayout.onHolderChange(option); - if (option.equals(PlayerOptions.SHOW_CRAFTING_GRID)) { - var buttonPanel = component(StackLayout.class, "entity_button_panel"); + if (!option.equals(PlayerOptions.SHOW_CRAFTING_GRID)) return; - var craftingBtn = buttonPanel.childById(io.wispforest.owo.ui.core.Component.class, "crafting_grid_btn"); + var buttonPanel = rootComponent().childById(StackLayout.class, "entity_button_panel"); + var craftingBtn = buttonPanel != null ? buttonPanel.childById(io.wispforest.owo.ui.core.UIComponent.class, "crafting_grid_btn") : null; - if (craftingBtn != null && Accessories.config().screenOptions.alwaysShowCraftingGrid()) { - buttonPanel.removeChild(craftingBtn); - } else if (craftingBtn == null && Accessories.config().screenOptions.alwaysShowCraftingGrid()) { - buttonPanel.child(buttonPanel.children().size() - 1, createCraftingToggleButton()); - } + if (craftingBtn != null && Accessories.config().screenOptions.alwaysShowCraftingGrid()) { + buttonPanel.removeChild(craftingBtn); + } else if (craftingBtn == null && Accessories.config().screenOptions.alwaysShowCraftingGrid()) { + buttonPanel.child(buttonPanel.children().size() - 1, createCraftingToggleButton()); } } private void toggleAdvancedOptions(ButtonComponent btn) { - boolean value = !(boolean) this.getDefaultedData(PlayerOptions.ADVANCED_SETTINGS); - this.setData(PlayerOptions.ADVANCED_SETTINGS, value); - - btn.tooltip(createToggleText("advanced_options", true, this.getDefaultedData(PlayerOptions.ADVANCED_SETTINGS))); + btn.tooltip(createToggleText("advanced_options", true, this.setDataFrom(PlayerOptions.ADVANCED_SETTINGS, BooleanUnaryOperator.negation()))); this.swapBottomComponentHolder(); } @@ -1164,10 +1527,6 @@ protected ExtendedSlotComponent(int index) { this.index = index; this.didDraw = true; - - if (slot() instanceof AccessoriesBasedSlot accessoriesBasedSlot) { - this.tooltip(accessoriesBasedSlot.getTooltipData()); - } } public final Slot slot() { @@ -1178,22 +1537,20 @@ public final Slot slot() { public void dismount(DismountReason reason) { super.dismount(reason); - if (reason == DismountReason.REMOVED) { - ((SlotAccessor) slot).owo$setX(-300); - ((SlotAccessor) slot).owo$setY(-300); - } + if (reason == DismountReason.REMOVED) hideSlot(slot); } @Override - public void draw(OwoUIDrawContext context, int mouseX, int mouseY, float partialTicks, float delta) { - //super.draw(context, mouseX, mouseY, partialTicks, delta); + public void draw(OwoUIGraphics context, int mouseX, int mouseY, float partialTicks, float delta) { + // DO NOT CALL SUPER AS SCISSOR ISSUES OCCUR + this.didDraw = true; ((OwoSlotExtension) this.slot).owo$setDisabledOverride(false); } @Override - public void drawTooltip(OwoUIDrawContext context, int mouseX, int mouseY, float partialTicks, float delta) { + public void drawTooltip(OwoUIGraphics context, int mouseX, int mouseY, float partialTicks, float delta) { var slot = this.slot(); if(slot != null) { @@ -1210,15 +1567,25 @@ public void drawTooltip(OwoUIDrawContext context, int mouseX, int mouseY, float } } - //context.translate(0, 0, 600); super.drawTooltip(context, mouseX, mouseY, partialTicks, delta); - //context.translate(0, 0, -600); + AccessoriesScreenBase.FORCE_TOOLTIP_LEFT.setValue(false); } } //-- + public void showCosmeticState(boolean value) { + this.setData(PlayerOptions.SHOW_COSMETIC_SLOTS, value); + + AccessoriesNetworking.sendToServer(PlayerOptions.SHOW_COSMETIC_SLOTS.toPacket(value)); + } + + public boolean showCosmeticState() { + return this.getDefaultedData(PlayerOptions.SHOW_COSMETIC_SLOTS); + } + + @Override public Optional getData(PlayerOption option) { return option.getData(this.menu.owner()) @@ -1233,4 +1600,10 @@ public Optional getData(PlayerOption option) { public void setData(PlayerOption option, T data) { option.setData(this.menu.owner(), data); } + + public T setDataFrom(PlayerOption option, UnaryOperator operator) { + var value = operator.apply(getData(option).orElseThrow()); + setData(option, value); + return value; + } } diff --git a/common/src/main/java/io/wispforest/accessories/client/gui/AccessoriesScreenBase.java b/common/src/main/java/io/wispforest/accessories/client/gui/AccessoriesScreenBase.java index 24dc70033..1dd101c5f 100644 --- a/common/src/main/java/io/wispforest/accessories/client/gui/AccessoriesScreenBase.java +++ b/common/src/main/java/io/wispforest/accessories/client/gui/AccessoriesScreenBase.java @@ -3,20 +3,42 @@ import io.wispforest.accessories.impl.option.PlayerOption; import io.wispforest.accessories.menu.SlotTypeAccessible; import io.wispforest.accessories.menu.variants.AccessoriesMenuBase; +import io.wispforest.accessories.mixin.client.DefaultTooltipPositionerMixin; import io.wispforest.accessories.networking.AccessoriesNetworking; import io.wispforest.accessories.networking.server.ContainerClose; import io.wispforest.accessories.pond.CloseContainerTransfer; +import io.wispforest.accessories.pond.DefaultTooltipPositionerExt; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.screens.inventory.InventoryScreen; import net.minecraft.client.gui.screens.inventory.MenuAccess; +import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipPositioner; +import net.minecraft.client.gui.screens.inventory.tooltip.DefaultTooltipPositioner; import net.minecraft.world.entity.LivingEntity; import org.apache.commons.lang3.mutable.MutableBoolean; +import org.apache.commons.lang3.mutable.MutableObject; import org.jetbrains.annotations.Nullable; +import org.joml.Vector2i; + +import java.util.function.UnaryOperator; public interface AccessoriesScreenBase extends MenuAccess { //-- + MutableObject ALTERATIVE_POSITIONER = new MutableObject<>(); + + static void setPositioner(boolean forceLeftTooltip) { + var positioner = ALTERATIVE_POSITIONER.getValue(); + + if (forceLeftTooltip && positioner == null) { + ALTERATIVE_POSITIONER.setValue((screenWidth, tooltipPos, tooltipWidth) -> { + if (tooltipPos.x + tooltipWidth <= screenWidth) tooltipPos.x = Math.max(tooltipPos.x - 24 - tooltipWidth, 4); + }); + } else if (positioner != null) { + ALTERATIVE_POSITIONER.setValue(null); + } + } + MutableBoolean FORCE_TOOLTIP_LEFT = new MutableBoolean(false); //-- diff --git a/common/src/main/java/io/wispforest/accessories/client/gui/ButtonEvents.java b/common/src/main/java/io/wispforest/accessories/client/gui/ButtonEvents.java index 53aded17b..599afac32 100644 --- a/common/src/main/java/io/wispforest/accessories/client/gui/ButtonEvents.java +++ b/common/src/main/java/io/wispforest/accessories/client/gui/ButtonEvents.java @@ -1,8 +1,8 @@ package io.wispforest.accessories.client.gui; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.gui.components.AbstractButton; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; public class ButtonEvents { @@ -13,6 +13,6 @@ public static B adjustRendering(B button, AdjustRende } public interface AdjustRendering { - boolean render(AbstractButton button, GuiGraphics instance, ResourceLocation sprite, int x, int y, int width, int height); + boolean render(AbstractButton button, GuiGraphicsExtractor instance, Identifier sprite, int x, int y, int width, int height); } } diff --git a/common/src/main/java/io/wispforest/accessories/client/gui/ComponentKey.java b/common/src/main/java/io/wispforest/accessories/client/gui/ComponentKey.java new file mode 100644 index 000000000..4786b8fc6 --- /dev/null +++ b/common/src/main/java/io/wispforest/accessories/client/gui/ComponentKey.java @@ -0,0 +1,59 @@ +package io.wispforest.accessories.client.gui; + +import io.wispforest.owo.ui.core.ParentUIComponent; +import io.wispforest.owo.ui.core.UIComponent; +import org.jetbrains.annotations.Nullable; + +public abstract class ComponentKey { + + static ComponentKey of(Class clazz, String id) { + return new ComponentKey() { + @Override + public Class clazz() { + return clazz; + } + + @Override + public String id() { + return id; + } + }; + } + + public abstract Class clazz(); + + public abstract String id(); + + public final boolean removeFromRoot(ParentUIComponent parent) { + var component = getFrom(parent); + return component != null && component.parent() != null && removeFrom(component.parent()); + } + + public final boolean removeFrom(ParentUIComponent parent) { + var component = getFrom(parent); + if (component != null) parent.removeChild(component); + return component != null; + } + + @SafeVarargs + public final

boolean removeFrom(ParentUIComponent parent, ComponentKey

... keys) { + for (var key : keys) { + if (parent == null) return false; + parent = key.getFrom(parent); + } + + return removeFrom(parent); + } + + public final @Nullable T getFrom(ParentUIComponent parent) { + return parent.childById(clazz(), id()); + } + + public final boolean has(ParentUIComponent parent) { + return getFrom(parent) != null; + } + + public final C withId(C c) { + return (C) c.id(id()); + } +} diff --git a/common/src/main/java/io/wispforest/accessories/client/gui/ToggleButton.java b/common/src/main/java/io/wispforest/accessories/client/gui/ToggleButton.java index 13b6f2c3c..29be2e78c 100644 --- a/common/src/main/java/io/wispforest/accessories/client/gui/ToggleButton.java +++ b/common/src/main/java/io/wispforest/accessories/client/gui/ToggleButton.java @@ -5,26 +5,35 @@ import io.wispforest.accessories.networking.AccessoriesNetworking; import io.wispforest.accessories.networking.server.SyncCosmeticToggle; import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.components.Tooltip; import net.minecraft.client.gui.components.WidgetSprites; import net.minecraft.client.input.InputWithModifiers; import net.minecraft.client.renderer.RenderPipelines; import net.minecraft.network.chat.Component; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.util.ARGB; import net.minecraft.util.Mth; import org.jetbrains.annotations.Nullable; import java.util.function.Consumer; -public class ToggleButton extends Button { +import net.fabricmc.fabric.api.event.Event; +import net.fabricmc.fabric.api.event.EventFactory; + +public class ToggleButton extends Button implements AbstractButtonExtension { + + private final Event ADJUST_RENDERING_EVENT = EventFactory.createArrayBacked(ButtonEvents.AdjustRendering.class, invokers -> (button, instance, sprite, x, y, width, height) -> { + boolean shouldCancel = false; + for (var invoker : invokers) shouldCancel = invoker.render(button, instance, sprite, x, y, width, height); + return shouldCancel; + }); private static final WidgetSprites SPRITES = new WidgetSprites( - ResourceLocation.withDefaultNamespace("widget/button"), - ResourceLocation.withDefaultNamespace("widget/button_disabled"), - ResourceLocation.withDefaultNamespace("widget/button_highlighted")); + Identifier.withDefaultNamespace("widget/button"), + Identifier.withDefaultNamespace("widget/button_disabled"), + Identifier.withDefaultNamespace("widget/button_highlighted")); private boolean toggled = false; @@ -82,10 +91,9 @@ public static ToggleButton.Builder toggleBuilder(Component message, Button.OnPre } @Override - protected void renderWidget(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTick) { + protected void extractContents(GuiGraphicsExtractor guiGraphics, int mouseX, int mouseY, float partialTick) { this.onRender.accept(this); - var minecraft = Minecraft.getInstance(); guiGraphics.blitSprite( RenderPipelines.GUI_TEXTURED, SPRITES.get(this.toggled(), this.isHoveredOrFocused()), @@ -95,8 +103,11 @@ protected void renderWidget(GuiGraphics guiGraphics, int mouseX, int mouseY, flo this.getHeight(), ARGB.white(this.alpha) ); - int i = this.active ? 16777215 : 10526880; - this.renderString(guiGraphics, minecraft.font, i | Mth.ceil(this.alpha * 255.0F) << 24); + } + + @Override + public Event getRenderingEvent() { + return ADJUST_RENDERING_EVENT; } public static class Builder { diff --git a/common/src/main/java/io/wispforest/accessories/client/gui/components/AccessoriesContainingLayout.java b/common/src/main/java/io/wispforest/accessories/client/gui/components/AccessoriesContainingLayout.java index d5687178f..8c0fdc7e6 100644 --- a/common/src/main/java/io/wispforest/accessories/client/gui/components/AccessoriesContainingLayout.java +++ b/common/src/main/java/io/wispforest/accessories/client/gui/components/AccessoriesContainingLayout.java @@ -3,7 +3,7 @@ import io.wispforest.accessories.api.menu.AccessoriesBasedSlot; import io.wispforest.accessories.client.gui.AccessoriesScreen; import io.wispforest.accessories.impl.option.PlayerOptions; -import io.wispforest.owo.ui.container.Containers; +import io.wispforest.owo.ui.container.UIContainers; import io.wispforest.owo.ui.container.FlowLayout; import io.wispforest.owo.ui.core.Insets; import io.wispforest.owo.ui.core.PositionedRectangle; @@ -89,8 +89,8 @@ public Boolean isHovering_Logical(Slot slot, double mouseX, double mouseY) { //-- protected static BaseLayoutGroup createBaseLayoutGroup(AccessoriesScreen screen, List slots, int totalRowCount, int maxColumnCount, int colStartingIndexOffset, boolean sideBySide) { - var accessoriesLayout = Containers.verticalFlow(Sizing.content(), Sizing.content()); - var cosmeticsLayout = Containers.verticalFlow(Sizing.content(), Sizing.content()); + var accessoriesLayout = UIContainers.verticalFlow(Sizing.content(), Sizing.content()); + var cosmeticsLayout = UIContainers.verticalFlow(Sizing.content(), Sizing.content()); var accessoriesChecks = new ArrayList(); var cosmeticChecks = new ArrayList(); @@ -100,10 +100,10 @@ protected static BaseLayoutGroup createBaseLayoutGroup(AccessoriesScreen screen, for (int row = 0; row < totalRowCount; row++) { var colStartingIndex = colStartingIndexOffset + (row * (maxColumnCount * 2)); - var accessoriesRowLayout = (FlowLayout) Containers.horizontalFlow(Sizing.content(), Sizing.content()) + var accessoriesRowLayout = (FlowLayout) UIContainers.horizontalFlow(Sizing.content(), Sizing.content()) .id("row_" + row); - var cosmeticRowLayout = (FlowLayout) Containers.horizontalFlow(Sizing.content(), Sizing.content()) + var cosmeticRowLayout = (FlowLayout) UIContainers.horizontalFlow(Sizing.content(), Sizing.content()) .id("row_" + row); var accessoriesRowButtons = new ArrayList(); @@ -188,8 +188,8 @@ default int height() { protected record BaseLayoutGroup(FlowLayout accessoriesLayout, FlowLayout cosmeticLayout, List accessoriesBtnChecks, List cosmeticBtnChecks, int totalColumnCount) { public static final BaseLayoutGroup DEFAULT = new BaseLayoutGroup( - Containers.verticalFlow(Sizing.content(), Sizing.content()), - Containers.verticalFlow(Sizing.content(), Sizing.content()), + UIContainers.verticalFlow(Sizing.content(), Sizing.content()), + UIContainers.verticalFlow(Sizing.content(), Sizing.content()), List.of(), List.of(), 0); diff --git a/common/src/main/java/io/wispforest/accessories/client/gui/components/AccessoriesScreenSettingsLayout.java b/common/src/main/java/io/wispforest/accessories/client/gui/components/AccessoriesScreenSettingsLayout.java index 037895ba3..c18adb5e8 100644 --- a/common/src/main/java/io/wispforest/accessories/client/gui/components/AccessoriesScreenSettingsLayout.java +++ b/common/src/main/java/io/wispforest/accessories/client/gui/components/AccessoriesScreenSettingsLayout.java @@ -8,9 +8,9 @@ import io.wispforest.accessories.mixin.client.owo.DiscreteSliderComponentAccessor; import io.wispforest.accessories.networking.AccessoriesNetworking; import io.wispforest.owo.ui.component.ButtonComponent; -import io.wispforest.owo.ui.component.Components; +import io.wispforest.owo.ui.component.UIComponents; import io.wispforest.owo.ui.component.DiscreteSliderComponent; -import io.wispforest.owo.ui.container.Containers; +import io.wispforest.owo.ui.container.UIContainers; import io.wispforest.owo.ui.container.FlowLayout; import io.wispforest.owo.ui.container.GridLayout; import io.wispforest.owo.ui.core.*; @@ -71,16 +71,14 @@ public Optional getData(PlayerOption option) { public void setData(PlayerOption option, T data) { optionAccess.setData(option, data); - if (updateLive) { - onHolderChange(option); - } + if (updateLive) onHolderChange(option); } public interface ComponentAccess { @Nullable - T getComponent(Class clazz, String id); + T getComponent(Class clazz, String id); - default void adjustIfPresent(Class clazz, String id, Consumer callback) { + default void adjustIfPresent(Class clazz, String id, Consumer callback) { var component = getComponent(clazz, id); if (component != null) callback.accept(component); @@ -101,11 +99,11 @@ private void syncToServer(R packet) { } private void buildLayout() { - List children = new ArrayList<>(); + List children = new ArrayList<>(); children.add( wrapAsSettings(PlayerOptions.COLUMN_AMOUNT, - Components.discreteSlider(Sizing.fixed(45), getMinimumColumnAmount(), getMaximumColumnAmount()) + UIComponents.discreteSlider(Sizing.fixed(45), getMinimumColumnAmount(), getMaximumColumnAmount()) .configure((DiscreteSliderComponent slider) -> { slider.snap(true) .setFromDiscreteValue(this.getDefaultedData(PlayerOptions.COLUMN_AMOUNT)) @@ -123,7 +121,7 @@ private void buildLayout() { children.add( wrapAsSettings(PlayerOptions.WIDGET_TYPE, - Components.button( + UIComponents.button( widgetTypeToggleMessage(this.getDefaultedData(PlayerOptions.WIDGET_TYPE), false), btn -> { var newWidget = this.getDefaultedData(PlayerOptions.WIDGET_TYPE) + 1; @@ -221,7 +219,7 @@ private void buildLayout() { } )); - var baseOptionPanel = Containers.grid(Sizing.fixed(maxWidth), Sizing.content(), (int) Math.ceil(children.size() / (float) columnAmount), columnAmount) + var baseOptionPanel = UIContainers.grid(Sizing.fixed(maxWidth), Sizing.content(), (int) Math.ceil(children.size() / (float) columnAmount), columnAmount) .configure((GridLayout component) -> { component .verticalAlignment(VerticalAlignment.CENTER) @@ -244,51 +242,51 @@ private void buildLayout() { } } - this.child(Containers.verticalScroll(Sizing.expand(), Sizing.expand(), baseOptionPanel)); + this.child(UIContainers.verticalScroll(Sizing.expand(), Sizing.expand(), baseOptionPanel)); } private int getEntryWidth() { return (maxWidth - 14) / columnAmount; } - private Component ofSettingsToggle(PlayerOption playerOption, BiConsumer, Boolean> onChange) { + private UIComponent ofSettingsToggle(PlayerOption playerOption, BiConsumer, Boolean> onChange) { return ofSettingsToggle(playerOption.name(), () -> this.getDefaultedData(playerOption), newValue -> { this.setData(playerOption, newValue); onChange.accept(playerOption, newValue); }); } - private Component ofSettingsToggle(String name, Supplier getter, Consumer setter) { + private UIComponent ofSettingsToggle(String name, Supplier getter, Consumer setter) { return wrapAsSettings( name, - Components.button( + UIComponents.button( createToggleText(name, false, getter.get()), btn -> { var newValue = !getter.get(); - btn.setMessage(createToggleText(name, false, newValue)); - btn.tooltip(createToggleText(name, true, newValue)); + btn.setMessage(createToggleText(name, false, newValue)); + btn.tooltip(createToggleText(name, true, newValue)); - setter.accept(newValue); - }) - .renderer(ComponentUtils.getButtonRenderer()) - .tooltip(createToggleText(name, true, getter.get())) + setter.accept(newValue); + }) + .renderer(ComponentUtils.getButtonRenderer()) + .tooltip(createToggleText(name, true, getter.get())) ); } - private Component wrapAsSettings(PlayerOption playerOption, Component component) { + private UIComponent wrapAsSettings(PlayerOption playerOption, UIComponent component) { return wrapAsSettings(playerOption.name(), component); } - private Component wrapAsSettings(String name, Component component) { + private UIComponent wrapAsSettings(String name, UIComponent component) { return createBaseParent() .gap(0) - .child(Components.label(Accessories.translation(name + ".label")).margins(Insets.left(1))) + .child(UIComponents.label(Accessories.translation(name + ".label")).margins(Insets.left(1))) .child(component.id(name).horizontalSizing(Sizing.fixed(getEntryWidth())).verticalSizing(Sizing.fixed(14))); } private FlowLayout createBaseParent() { - return Containers.verticalFlow(Sizing.fixed(getEntryWidth()), Sizing.fixed(23)); + return UIContainers.verticalFlow(Sizing.fixed(getEntryWidth()), Sizing.fixed(23)); } private static net.minecraft.network.chat.Component widgetTypeToggleMessage(int value, boolean isTooltip) { diff --git a/common/src/main/java/io/wispforest/accessories/client/gui/components/ArrowComponent.java b/common/src/main/java/io/wispforest/accessories/client/gui/components/ArrowComponent.java index 73bcd7dc7..f5ad1a47d 100644 --- a/common/src/main/java/io/wispforest/accessories/client/gui/components/ArrowComponent.java +++ b/common/src/main/java/io/wispforest/accessories/client/gui/components/ArrowComponent.java @@ -2,15 +2,15 @@ import io.wispforest.accessories.Accessories; import io.wispforest.accessories.client.DrawUtils; -import io.wispforest.owo.ui.base.BaseComponent; +import io.wispforest.owo.ui.base.BaseUIComponent; import io.wispforest.owo.ui.core.AnimatableProperty; -import io.wispforest.owo.ui.core.OwoUIDrawContext; +import io.wispforest.owo.ui.core.OwoUIGraphics; import io.wispforest.owo.ui.core.PositionedRectangle; import io.wispforest.owo.ui.core.Sizing; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; -public class ArrowComponent extends BaseComponent { - protected final ResourceLocation texture = Accessories.of("textures/gui/theme/all_arrow_directions.png"); +public class ArrowComponent extends BaseUIComponent { + protected final Identifier texture = Accessories.of("textures/gui/theme/all_arrow_directions.png"); protected final int textureWidth = 32; protected final int textureHeight = 32; @@ -54,7 +54,7 @@ public void update(float delta, int mouseX, int mouseY) { this.visibleArea.update(delta); } - public void draw(OwoUIDrawContext context, int mouseX, int mouseY, float partialTicks, float delta) { + public void draw(OwoUIGraphics context, int mouseX, int mouseY, float partialTicks, float delta) { context.push(); context.translate((float) this.x, (float) this.y); diff --git a/common/src/main/java/io/wispforest/accessories/client/gui/components/ComponentUtils.java b/common/src/main/java/io/wispforest/accessories/client/gui/components/ComponentUtils.java index e1209c4da..6775ef4f1 100644 --- a/common/src/main/java/io/wispforest/accessories/client/gui/components/ComponentUtils.java +++ b/common/src/main/java/io/wispforest/accessories/client/gui/components/ComponentUtils.java @@ -9,10 +9,10 @@ import io.wispforest.accessories.networking.AccessoriesNetworking; import io.wispforest.accessories.networking.server.SyncCosmeticToggle; import io.wispforest.accessories.pond.ScissorStackManipulation; -import io.wispforest.owo.ui.base.BaseOwoHandledScreen; +import io.wispforest.owo.ui.base.BaseOwoContainerScreen; import io.wispforest.owo.ui.component.ButtonComponent; -import io.wispforest.owo.ui.component.Components; -import io.wispforest.owo.ui.container.Containers; +import io.wispforest.owo.ui.component.UIComponents; +import io.wispforest.owo.ui.container.UIContainers; import io.wispforest.owo.ui.container.FlowLayout; import io.wispforest.owo.ui.container.ScrollContainer; import io.wispforest.owo.ui.core.*; @@ -23,7 +23,7 @@ import net.minecraft.client.Minecraft; import net.minecraft.data.AtlasIds; import net.minecraft.network.chat.Component; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.world.inventory.Slot; import net.minecraft.world.item.CreativeModeTab; import org.jetbrains.annotations.Nullable; @@ -34,13 +34,13 @@ import java.util.WeakHashMap; import java.util.function.*; -import static io.wispforest.owo.ui.container.Containers.horizontalFlow; -import static io.wispforest.owo.ui.container.Containers.verticalFlow; +import static io.wispforest.owo.ui.container.UIContainers.horizontalFlow; +import static io.wispforest.owo.ui.container.UIContainers.verticalFlow; public class ComponentUtils { - private static final ResourceLocation SLOT = ResourceLocation.withDefaultNamespace("textures/gui/sprites/container/slot.png"); - private static final ResourceLocation DARK_SLOT = Accessories.of("textures/gui/theme/dark/slot.png"); + private static final Identifier SLOT = Identifier.withDefaultNamespace("textures/gui/sprites/container/slot.png"); + private static final Identifier DARK_SLOT = Accessories.of("textures/gui/theme/dark/slot.png"); public static final Surface BACKGROUND_SLOT_RENDERING_SURFACE = (context, component) -> { var slotComponents = new ArrayList(); @@ -76,11 +76,11 @@ public class ComponentUtils { renderSpectrumOutlines(context, slotComponents); }; - public static void renderSpectrumOutlines(OwoUIDrawContext context, List slotComponents) { + public static void renderSpectrumOutlines(OwoUIGraphics context, List slotComponents) { for (var slotComponent : slotComponents) { var slot = slotComponent.slot(); - if (!(slot instanceof SlotTypeAccessible slotTypeAccessible) || !slotTypeAccessible.isCosmeticSlot()) continue; + if (!(slot instanceof SlotTypeAccessible access) || !access.isCosmeticSlot()) continue; DrawUtils.drawRectOutlineWithSpectrum(context, slotComponent.x(), slotComponent.y(), 16, 16, 0.35f, false); } @@ -91,7 +91,7 @@ public static void renderSpectrumOutlines(OwoUIDrawContext context, List void addModeCheckHook(T lightMode, T darkMode, O o, Predica setCallback.accept(o, getterFunc.apply(Accessories.config().screenOptions.isDarkMode())); } - public static ResourceLocation getSlotTexture() { + public static Identifier getSlotTexture() { return checkMode(SLOT, DARK_SLOT); } @@ -188,24 +188,24 @@ public static ScrollContainer.Scrollbar getScrollbarRenderer() { return VANILLA; } - public static void recursiveSearchSlots(ParentComponent parentComponent, Consumer action) { + public static void recursiveSearchSlots(ParentUIComponent parentComponent, Consumer action) { recursiveSearch(parentComponent, AccessoriesScreen.ExtendedSlotComponent.class, action); } - public static void recursiveSearch(ParentComponent parentComponent, Class target, Consumer action) { + public static void recursiveSearch(ParentUIComponent parentComponent, Class target, Consumer action) { if(parentComponent == null) return; for (var child : parentComponent.children()) { if(target.isInstance(child)) action.accept((C) child); - if(child instanceof ParentComponent childParent) recursiveSearch(childParent, target, action); + if(child instanceof ParentUIComponent childParent) recursiveSearch(childParent, target, action); } } - public static Pair createSlotWithToggle(S slot, Function slotBuilder) { + public static Pair createSlotWithToggle(S slot, Function slotBuilder) { return createSlotWithToggle(slot, slotBuilder, true); } - public static Pair createSlotWithToggle(S slot, Function slotBuilder, boolean createButton) { + public static Pair createSlotWithToggle(S slot, Function slotBuilder, boolean createButton) { var btnPosition = Positioning.absolute(14, -1); //15, -1 @Nullable ButtonComponent toggleBtn = null; @@ -243,7 +243,7 @@ public static ButtonComponent createSlotTo (context, button, delta) -> {}); } - public static io.wispforest.owo.ui.core.Component createGroupToggle(AccessoriesScreen screen, SlotGroup group) { + public static io.wispforest.owo.ui.core.UIComponent createGroupToggle(AccessoriesScreen screen, SlotGroup group) { var tooltipData = new ArrayList(); tooltipData.add(Component.translatable(group.translation())); @@ -291,22 +291,22 @@ public static ButtonComponent createToggle(Supplier stateSupplier, Cons context.pop(); }; - return Components.button(Component.empty(), onToggle) + return UIComponents.button(Component.empty(), onToggle) .renderer(texturedRenderer); } - public static io.wispforest.owo.ui.core.Component createIconButton(Consumer action, int size, Consumer builder, Function textureGetter) { + public static io.wispforest.owo.ui.core.UIComponent createIconButton(Consumer action, int size, Consumer builder, Function textureGetter) { return createIconButton(action, size, null, builder, (context, buttonComponent) -> textureGetter.apply(buttonComponent)); } - public static io.wispforest.owo.ui.core.Component createIconButton(Consumer action, int size, Consumer builder, BiFunction textureGetter) { + public static io.wispforest.owo.ui.core.UIComponent createIconButton(Consumer action, int size, Consumer builder, BiFunction textureGetter) { return createIconButton(action, size, null, builder, textureGetter); } - public static io.wispforest.owo.ui.core.Component createIconButton(Consumer action, int size, String id, Consumer builder, BiFunction textureGetter) { + public static io.wispforest.owo.ui.core.UIComponent createIconButton(Consumer action, int size, String id, Consumer builder, BiFunction textureGetter) { return verticalFlow(Sizing.content(), Sizing.content()) .child( - Components.button(Component.empty(), action) + UIComponents.button(Component.empty(), action) .sizing(Sizing.fixed(size)) .configure(builder) .renderer((ctx, btn, delta) -> { @@ -317,7 +317,7 @@ public static io.wispforest.owo.ui.core.Component createIconButton(Consumer io.wispforest.owo.ui.core.Component createCraftingComponent(int start, Function componentFactory, Consumer slotEnabler, boolean isVertical) { + public static io.wispforest.owo.ui.core.UIComponent createCraftingComponent(int start, Function componentFactory, Consumer slotEnabler, boolean isVertical) { for (int i = start; i < 5 + start; i++) slotEnabler.accept(i); var craftingLayout = isVertical ? verticalFlow(Sizing.fixed(18 * 2), Sizing.content()) : horizontalFlow(Sizing.content(), Sizing.fixed(18 * 2)); @@ -344,12 +344,12 @@ public static io.wispforest.owo.u .horizontalAlignment(HorizontalAlignment.CENTER) .verticalAlignment(VerticalAlignment.CENTER); - return Containers.verticalFlow(Sizing.content(), Sizing.content()) + return UIContainers.verticalFlow(Sizing.content(), Sizing.content()) .child(craftingLayout) .padding(Insets.of(7, 7, 4, 7)); } - public static io.wispforest.owo.ui.core.Component createPlayerInv(int start, int end, Function componentFactory, Consumer slotEnabler) { + public static io.wispforest.owo.ui.core.UIComponent createPlayerInv(int start, int end, Function componentFactory, Consumer slotEnabler) { var playerLayout = verticalFlow(Sizing.content(), Sizing.content()); int row = 0; diff --git a/common/src/main/java/io/wispforest/accessories/client/gui/components/ExtendedScrollContainer.java b/common/src/main/java/io/wispforest/accessories/client/gui/components/ExtendedScrollContainer.java index de3fef7ec..c06612ce5 100644 --- a/common/src/main/java/io/wispforest/accessories/client/gui/components/ExtendedScrollContainer.java +++ b/common/src/main/java/io/wispforest/accessories/client/gui/components/ExtendedScrollContainer.java @@ -8,7 +8,7 @@ import java.util.List; -public class ExtendedScrollContainer extends ScrollContainer { +public class ExtendedScrollContainer extends ScrollContainer { protected TriConsumer, Double, Double> scrolledTo = (container, prevOffset, currentOffset) -> {}; @@ -136,7 +136,7 @@ public boolean onMouseScroll(double mouseX, double mouseY, double amount) { } @Override - protected void drawChildren(OwoUIDrawContext context, int mouseX, int mouseY, float partialTicks, float delta, List children) { + protected void drawChildren(OwoUIGraphics context, int mouseX, int mouseY, float partialTicks, float delta, List children) { if (this.customClippingInsets != Insets.none()) { context.enableScissor(this.x + customClippingInsets.left(), this.y + customClippingInsets.top(), diff --git a/common/src/main/java/io/wispforest/accessories/client/gui/components/InventoryEntityComponent.java b/common/src/main/java/io/wispforest/accessories/client/gui/components/InventoryEntityComponent.java index 25c410e3f..8166eca1a 100644 --- a/common/src/main/java/io/wispforest/accessories/client/gui/components/InventoryEntityComponent.java +++ b/common/src/main/java/io/wispforest/accessories/client/gui/components/InventoryEntityComponent.java @@ -1,9 +1,10 @@ package io.wispforest.accessories.client.gui.components; import com.mojang.math.Axis; +import io.wispforest.accessories.pond.GuiGraphicsAccess; import io.wispforest.owo.ui.component.EntityComponent; -import io.wispforest.owo.ui.core.Component; -import io.wispforest.owo.ui.core.OwoUIDrawContext; +import io.wispforest.owo.ui.core.UIComponent; +import io.wispforest.owo.ui.core.OwoUIGraphics; import io.wispforest.owo.ui.core.Sizing; import io.wispforest.owo.ui.renderstate.EntityElementRenderState; import net.minecraft.client.gui.navigation.ScreenRectangle; @@ -85,9 +86,9 @@ private float getEntityScale() { public float xOffset = 0.0f; public float yOffset = 0.0f; - private TriConsumer> renderWrapping = (ctx, component, runnables) -> runnables.forEach(Runnable::run); + private TriConsumer> renderWrapping = (ctx, component, runnables) -> runnables.forEach(Runnable::run); - public InventoryEntityComponent renderWrapping(TriConsumer> renderWrapping) { + public InventoryEntityComponent renderWrapping(TriConsumer> renderWrapping) { this.renderWrapping = renderWrapping; return this; @@ -144,7 +145,7 @@ public InventoryEntityComponent scaleToFitHorizontally(boolean scaleToFit) { } @Override - public void draw(OwoUIDrawContext context, int mouseX, int mouseY, float partialTicks, float delta) { + public void draw(OwoUIGraphics context, int mouseX, int mouseY, float partialTicks, float delta) { if(!(entity instanceof LivingEntity living)) { super.draw(context, mouseX, mouseY, partialTicks, delta); @@ -190,7 +191,7 @@ public void draw(OwoUIDrawContext context, int mouseX, int mouseY, float partial ); } - private void renderLiving(OwoUIDrawContext context, LivingEntity living, int mouseX, int mouseY, float partialTicks, boolean isLeftSide) { + private void renderLiving(OwoUIGraphics context, LivingEntity living, int mouseX, int mouseY, float partialTicks, boolean isLeftSide) { var matrix = new Matrix4f(); transformMatrixStack(matrix, isLeftSide); @@ -233,15 +234,16 @@ private void renderLiving(OwoUIDrawContext context, LivingEntity living, int mou } entityState.lightCoords = 15728880; - entityState.hitboxesRenderState = null; + // hitboxesRenderState field removed in 1.21.11 (debug hitbox rendering moved elsewhere) entityState.shadowPieces.clear(); entityState.outlineColor = 0; - context.guiRenderState.submitPicturesInPictureState(new EntityElementRenderState( + var gfxAccess = (GuiGraphicsAccess) (Object) context; + gfxAccess.accessories$guiRenderState().addPicturesInPictureState(new EntityElementRenderState( entityState, matrix, new ScreenRectangle(this.x, this.y, this.width, this.height), - context.scissorStack.peek() + gfxAccess.accessories$scissorStack().peek() )); } diff --git a/common/src/main/java/io/wispforest/accessories/client/gui/components/PaginatedAccessoriesLayout.java b/common/src/main/java/io/wispforest/accessories/client/gui/components/PaginatedAccessoriesLayout.java index 8f9e6e538..efa3fd866 100644 --- a/common/src/main/java/io/wispforest/accessories/client/gui/components/PaginatedAccessoriesLayout.java +++ b/common/src/main/java/io/wispforest/accessories/client/gui/components/PaginatedAccessoriesLayout.java @@ -3,9 +3,9 @@ import io.wispforest.accessories.Accessories; import io.wispforest.accessories.client.gui.AccessoriesScreen; import io.wispforest.accessories.impl.option.PlayerOptions; -import io.wispforest.owo.ui.component.Components; +import io.wispforest.owo.ui.component.UIComponents; import io.wispforest.owo.ui.component.LabelComponent; -import io.wispforest.owo.ui.container.Containers; +import io.wispforest.owo.ui.container.UIContainers; import io.wispforest.owo.ui.container.FlowLayout; import io.wispforest.owo.ui.core.*; import io.wispforest.owo.util.Observable; @@ -91,7 +91,7 @@ protected void buildLayout(RawPageData layoutData) { var currentPage = getCurrentPageOrDefault(); - var holder = Containers.horizontalFlow(Sizing.content(), Sizing.content()) + var holder = UIContainers.horizontalFlow(Sizing.content(), Sizing.content()) .configure((FlowLayout layout) -> { layout.gap(3) .id("accessories_container_holder"); @@ -107,7 +107,7 @@ protected void buildLayout(RawPageData layoutData) { holder.child(currentPage.getLayout(screen.showCosmeticState())); } - var accessoriesMainLayout = (FlowLayout) Containers.verticalFlow(Sizing.content(), Sizing.content()) + var accessoriesMainLayout = (FlowLayout) UIContainers.verticalFlow(Sizing.content(), Sizing.content()) .gap(2) .child(holder) .horizontalAlignment(HorizontalAlignment.RIGHT) @@ -121,7 +121,7 @@ protected void buildLayout(RawPageData layoutData) { return; } - var pageLabel = Components.label(Component.literal((pageIndex().get() + 1) + "/" + layoutData.pages().size())) + var pageLabel = UIComponents.label(Component.literal((pageIndex().get() + 1) + "/" + layoutData.pages().size())) .configure((LabelComponent labelComponent) -> { ComponentUtils.addModeCheckHook( Color.ofFormatting(ChatFormatting.DARK_GRAY), Color.ofFormatting(ChatFormatting.WHITE), @@ -133,9 +133,9 @@ protected void buildLayout(RawPageData layoutData) { pageIndex().observe(integer -> pageLabel.text(Component.literal((pageIndex().get() + 1) + "/" + layoutData.pages().size()))); - var titleBar = Containers.horizontalFlow(Sizing.fixed(currentPage.width(screen.showCosmeticState(), layoutData.sideBySide())), Sizing.content()) + var titleBar = UIContainers.horizontalFlow(Sizing.fixed(currentPage.width(screen.showCosmeticState(), layoutData.sideBySide())), Sizing.content()) .child( - Containers.horizontalFlow(Sizing.expand(100), Sizing.content()) + UIContainers.horizontalFlow(Sizing.expand(100), Sizing.content()) .child(pageLabel) .horizontalAlignment(HorizontalAlignment.CENTER) ) @@ -185,7 +185,7 @@ protected void buildLayout(RawPageData layoutData) { this.sizing(Sizing.content(), Sizing.fixed(minimumLayoutHeight)); this.child(accessoriesMainLayout); - this.child(Containers.verticalFlow(Sizing.content(), Sizing.expand())); + this.child(UIContainers.verticalFlow(Sizing.content(), Sizing.expand())); } private void switchPage(int pageOffset) { @@ -303,12 +303,12 @@ protected Iterable getAlternativeChecks(boolean showingCosm return this.getCurrentPageOrDefault().getAlternativeChecks(showingCosmetics); } - private void swapSlotStates(ParentComponent prevComp, ParentComponent newComp, boolean selectedPage) { + private void swapSlotStates(ParentUIComponent prevComp, ParentUIComponent newComp, boolean selectedPage) { toggleSlotStates(prevComp, false, selectedPage); toggleSlotStates(newComp, true, selectedPage); } - private void toggleSlotStates(ParentComponent component, boolean showSlots, boolean selectedPage) { + private void toggleSlotStates(ParentUIComponent component, boolean showSlots, boolean selectedPage) { if (!showSlots){ ComponentUtils.recursiveSearchSlots(component, slotComponent -> screen.disableSlot(slotComponent.slot())); } else { diff --git a/common/src/main/java/io/wispforest/accessories/client/gui/components/PixelPerfectTextureComponent.java b/common/src/main/java/io/wispforest/accessories/client/gui/components/PixelPerfectTextureComponent.java index c1887a39e..2fe969e63 100644 --- a/common/src/main/java/io/wispforest/accessories/client/gui/components/PixelPerfectTextureComponent.java +++ b/common/src/main/java/io/wispforest/accessories/client/gui/components/PixelPerfectTextureComponent.java @@ -1,24 +1,25 @@ package io.wispforest.accessories.client.gui.components; -import io.wispforest.owo.ui.base.BaseComponent; -import io.wispforest.owo.ui.core.OwoUIDrawContext; +import io.wispforest.accessories.pond.GuiGraphicsAccess; +import io.wispforest.owo.ui.base.BaseUIComponent; +import io.wispforest.owo.ui.core.OwoUIGraphics; import io.wispforest.owo.ui.core.Sizing; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.render.TextureSetup; -import net.minecraft.client.gui.render.state.BlitRenderState; +import net.minecraft.client.renderer.state.gui.BlitRenderState; import net.minecraft.client.renderer.RenderPipelines; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import org.joml.Matrix3x2f; -public class PixelPerfectTextureComponent extends BaseComponent { +public class PixelPerfectTextureComponent extends BaseUIComponent { - private final ResourceLocation texture; + private final Identifier texture; - public PixelPerfectTextureComponent(ResourceLocation texture, int textureWidth, int textureHeight, int scale) { + public PixelPerfectTextureComponent(Identifier texture, int textureWidth, int textureHeight, int scale) { this(texture, Sizing.fixed(textureWidth * scale), Sizing.fixed(textureHeight * scale)); } - public PixelPerfectTextureComponent(ResourceLocation texture, Sizing horizontalSizing, Sizing verticalSizing) { + public PixelPerfectTextureComponent(Identifier texture, Sizing horizontalSizing, Sizing verticalSizing) { super(); this.texture = texture; @@ -31,27 +32,30 @@ public PixelPerfectTextureComponent(ResourceLocation texture, Sizing horizontalS } @Override - public void draw(OwoUIDrawContext context, int mouseX, int mouseY, float partialTicks, float delta) { + public void draw(OwoUIGraphics context, int mouseX, int mouseY, float partialTicks, float delta) { drawPixelPerfectTextureQuad(context, texture, this.x(), this.y(), this.width(), this.height()); } - public static void drawPixelPerfectTextureQuad(OwoUIDrawContext context, ResourceLocation texture, int x1, int y1, int width, int height) { + public static void drawPixelPerfectTextureQuad(OwoUIGraphics context, Identifier texture, int x1, int y1, int width, int height) { int x2 = x1 + width; int y2 = y1 + height; - var gpuTextureView = Minecraft.getInstance().getTextureManager().getTexture(texture).getTextureView(); + var textureObj = Minecraft.getInstance().getTextureManager().getTexture(texture); + var gpuTextureView = textureObj.getTextureView(); + var gpuSampler = textureObj.getSampler(); - context.guiRenderState.submitGuiElement( + var access = (GuiGraphicsAccess) (Object) context; + access.accessories$guiRenderState().addGuiElement( new BlitRenderState( RenderPipelines.GUI_TEXTURED, - TextureSetup.singleTexture(gpuTextureView), + TextureSetup.singleTexture(gpuTextureView, gpuSampler), new Matrix3x2f(context.pose()), x1, y1, x2, y2, 0, 1, 0, 1, 0xFFFFFFFF, - context.scissorStack.peek() + access.accessories$scissorStack().peek() ) ); } diff --git a/common/src/main/java/io/wispforest/accessories/client/gui/components/ScrollableAccessoriesLayout.java b/common/src/main/java/io/wispforest/accessories/client/gui/components/ScrollableAccessoriesLayout.java index 3dfa4200c..e3bde4559 100644 --- a/common/src/main/java/io/wispforest/accessories/client/gui/components/ScrollableAccessoriesLayout.java +++ b/common/src/main/java/io/wispforest/accessories/client/gui/components/ScrollableAccessoriesLayout.java @@ -3,8 +3,8 @@ import io.wispforest.accessories.Accessories; import io.wispforest.accessories.client.gui.AccessoriesScreen; import io.wispforest.accessories.impl.option.PlayerOptions; -import io.wispforest.owo.ui.base.BaseParentComponent; -import io.wispforest.owo.ui.container.Containers; +import io.wispforest.owo.ui.base.BaseParentUIComponent; +import io.wispforest.owo.ui.container.UIContainers; import io.wispforest.owo.ui.container.FlowLayout; import io.wispforest.owo.ui.container.ScrollContainer; import io.wispforest.owo.ui.core.*; @@ -99,7 +99,7 @@ protected void buildLayout(RawScrollData layoutData) { FlowLayout fullLayout; if (layoutData.sideBySide()) { - fullLayout = Containers.horizontalFlow(Sizing.content(), Sizing.content()).gap(3); + fullLayout = UIContainers.horizontalFlow(Sizing.content(), Sizing.content()).gap(3); fullLayout.id("side_by_side_holder"); @@ -116,7 +116,7 @@ protected void buildLayout(RawScrollData layoutData) { fullLayout.padding(this.screen.getDefaultedData(PlayerOptions.MAIN_WIDGET_POSITION) ? Insets.left(paddingValue) : Insets.right(paddingValue)); - Component innerAccessoriesLayout; + io.wispforest.owo.ui.core.UIComponent innerAccessoriesLayout; var width = layoutData.width(); @@ -148,13 +148,13 @@ protected void buildLayout(RawScrollData layoutData) { .scrollbar(ComponentUtils.getScrollbarRenderer()) .id("accessories_scroll_container"); } else { - innerAccessoriesLayout = Containers.verticalFlow(Sizing.content(), Sizing.content()).child(fullLayout); + innerAccessoriesLayout = UIContainers.verticalFlow(Sizing.content(), Sizing.content()).child(fullLayout); } innerAccessoriesLayout .id("inner_accessories_container"); - var accessoriesMainLayout = (FlowLayout) Containers.verticalFlow(Sizing.content(), Sizing.content()) + var accessoriesMainLayout = (FlowLayout) UIContainers.verticalFlow(Sizing.content(), Sizing.content()) .gap(3) .child(innerAccessoriesLayout) .horizontalAlignment(HorizontalAlignment.RIGHT) @@ -171,7 +171,7 @@ protected void buildLayout(RawScrollData layoutData) { this.sizing(Sizing.content(), Sizing.fixed(minimumLayoutHeight)); this.child(accessoriesMainLayout); - this.child(Containers.verticalFlow(Sizing.content(), Sizing.expand())); + this.child(UIContainers.verticalFlow(Sizing.content(), Sizing.expand())); } @Override @@ -180,10 +180,10 @@ public void onCosmeticToggle(boolean showCosmeticState) { if (this.layoutData.sideBySide) { if (showCosmeticState) { - ParentComponent newLayout = baseGroupData.cosmeticLayout(); + ParentUIComponent newLayout = baseGroupData.cosmeticLayout(); for (int i = 0; i < layoutData.totalRowCount(); i++) { - var newRow = newLayout.childById(ParentComponent.class, "row_" + i); + var newRow = newLayout.childById(ParentUIComponent.class, "row_" + i); ComponentUtils.recursiveSearchSlots(newRow, (slotComponent) -> { this.screen.enableSlot(slotComponent.slot()); @@ -192,10 +192,10 @@ public void onCosmeticToggle(boolean showCosmeticState) { screen.component(FlowLayout.class, "side_by_side_holder").child(0, newLayout); } else { - ParentComponent prevLayout = baseGroupData.cosmeticLayout(); + ParentUIComponent prevLayout = baseGroupData.cosmeticLayout(); for (int i = 0; i < layoutData.totalRowCount(); i++) { - var oldRow = prevLayout.childById(ParentComponent.class, "row_" + i); + var oldRow = prevLayout.childById(ParentUIComponent.class, "row_" + i); ComponentUtils.recursiveSearchSlots(oldRow, (slotComponent) -> { this.screen.disableSlot(slotComponent.slot()); @@ -206,7 +206,7 @@ public void onCosmeticToggle(boolean showCosmeticState) { prevLayout.parent().removeChild(prevLayout); } - var scrollContainer = this.childById(ParentComponent.class, "inner_accessories_container"); + var scrollContainer = this.childById(ParentUIComponent.class, "inner_accessories_container"); if (scrollContainer instanceof ExtendedScrollContainer) { var width = layoutData.width(); @@ -218,7 +218,7 @@ public void onCosmeticToggle(boolean showCosmeticState) { screen.setupPadding(); } else { - var container = this.childById(BaseParentComponent.class, "inner_accessories_container"); + var container = this.childById(BaseParentUIComponent.class, "inner_accessories_container"); Consumer childSetter; @@ -234,10 +234,10 @@ public void onCosmeticToggle(boolean showCosmeticState) { return; } - ParentComponent prevLayout = showCosmeticState ? baseGroupData.accessoriesLayout() : baseGroupData.cosmeticLayout(); + ParentUIComponent prevLayout = showCosmeticState ? baseGroupData.accessoriesLayout() : baseGroupData.cosmeticLayout(); for (int i = 0; i < layoutData.totalRowCount(); i++) { - var oldRow = prevLayout.childById(ParentComponent.class, "row_" + i); + var oldRow = prevLayout.childById(ParentUIComponent.class, "row_" + i); ComponentUtils.recursiveSearchSlots(oldRow, (slotComponent) -> { this.screen.disableSlot(slotComponent.slot()); @@ -253,7 +253,7 @@ public void onCosmeticToggle(boolean showCosmeticState) { childSetter.accept(newLayout); for (int i = 0; i < layoutData.totalRowCount(); i++) { - var newRow = newLayout.childById(ParentComponent.class, "row_" + i); + var newRow = newLayout.childById(ParentUIComponent.class, "row_" + i); ComponentUtils.recursiveSearchSlots(newRow, (slotComponent) -> { this.screen.enableSlot(slotComponent.slot()); diff --git a/common/src/main/java/io/wispforest/accessories/commands/AccessoriesCommands.java b/common/src/main/java/io/wispforest/accessories/commands/AccessoriesCommands.java index 9cf2ee253..340f33cd1 100644 --- a/common/src/main/java/io/wispforest/accessories/commands/AccessoriesCommands.java +++ b/common/src/main/java/io/wispforest/accessories/commands/AccessoriesCommands.java @@ -14,6 +14,7 @@ import io.wispforest.accessories.api.attributes.SlotAttribute; import io.wispforest.accessories.api.client.rendering.RenderingFunction; import io.wispforest.accessories.api.components.*; +import io.wispforest.accessories.api.data.AccessoriesBaseData; import io.wispforest.accessories.commands.api.CommandGenerators; import io.wispforest.accessories.commands.api.CommandTreeGenerator; import io.wispforest.accessories.commands.api.base.BranchedCommandGenerator; @@ -24,6 +25,7 @@ import io.wispforest.accessories.data.SlotGroupLoader; import io.wispforest.accessories.data.SlotTypeLoader; import io.wispforest.accessories.mixin.CommandSelectionAccessor; +import io.wispforest.accessories.mixin.EnchantCommandAccessor; import io.wispforest.accessories.mixin.ResourceArgumentAccessor; import io.wispforest.endec.Endec; import net.minecraft.commands.CommandBuildContext; @@ -37,14 +39,19 @@ import net.minecraft.core.registries.Registries; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceKey; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.world.effect.MobEffectInstance; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.LivingEntity; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.server.players.NameAndId; import net.minecraft.world.entity.ai.attributes.Attribute; import net.minecraft.world.entity.ai.attributes.AttributeModifier; import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; +import net.minecraft.world.item.enchantment.Enchantment; +import net.minecraft.world.item.enchantment.EnchantmentHelper; import org.apache.commons.lang3.mutable.MutableBoolean; import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; @@ -91,7 +98,7 @@ public static LivingEntity getOrThrowLivingEntity(CommandContext NamedArgumentGetter getArgumentGetter(Argument @Nullable public static NamedArgumentGetter getArgumentGetterErased(ArgumentType type) { - if (type instanceof ResourceLocationArgument) return ResourceLocationArgument::getId; + if (type instanceof IdentifierArgument) return IdentifierArgument::getId; if (type instanceof ComponentArgument) return ComponentArgument::getResolvedComponent; if (type instanceof BoolArgumentType) return BoolArgumentType::getBool; if (type instanceof SlotArgumentType) return SlotArgumentType::getSlot; @@ -135,14 +142,21 @@ public NamedArgumentGetter getArgumentGetter(Argument } public void generateTrees(BranchedCommandGenerator root, CommandBuildContext context, Commands.CommandSelection environment) { - root.modifyRootNode(builder -> builder.requires(stack -> stack.hasPermission(Commands.LEVEL_GAMEMASTERS))); + root.modifyRootNode(builder -> builder.requires(stack -> { + var entity = stack.getEntity(); + if (entity instanceof ServerPlayer sp) { + return sp.level().getServer().getPlayerList().isOp(new NameAndId(sp.getGameProfile())); + } + var server = stack.getServer(); + return server != null && server.isSingleplayer(); + })); if (((CommandSelectionAccessor) (Object) environment).accessories$includeIntegrated()) { root.branch("rendering", renderingBranch -> { renderingBranch.leaves( "create-renderer-stack", - required("renderer_id", ResourceLocationArgument.id()), - required("item_model_id", ResourceLocationArgument.id()), + required("renderer_id", IdentifierArgument.id()), + required("item_model_id", IdentifierArgument.id()), required("custom_name", ComponentArgument.textComponent(context)), defaulted("is_bundle", BoolArgumentType.bool(), false), (ctx, rendererId, itemModelId, component, isBundle) -> { @@ -151,7 +165,7 @@ public void generateTrees(BranchedCommandGenerator root, CommandBuildContext con } ).leaves( "listen-to-renderer", - defaulted("item_model_id", ResourceLocationArgument.id(), null), + defaulted("item_model_id", IdentifierArgument.id(), null), (ctx, id) -> { CustomRendererLoader.constantFileResolving(ctx.getSource().getServer(), id); @@ -293,7 +307,7 @@ public void generateTrees(BranchedCommandGenerator root, CommandBuildContext con .branch( required("entity", EntityArgument.entity(), EntityArgument::getEntity), required("slot", SlotArgumentType.INSTANCE), - required("id", ResourceLocationArgument.id()), + required("id", IdentifierArgument.id()), branchBuilder -> { branchBuilder.leaves( "add", @@ -363,6 +377,52 @@ public void generateTrees(BranchedCommandGenerator root, CommandBuildContext con }); }); + root.branch("enchant", enchantBranch -> { + enchantBranch.leaves( + required("targets", EntityArgument.entities(), EntityArgument::getEntities), + required("enchantment", ResourceArgument.resource(context, Registries.ENCHANTMENT), ResourceArgument::getEnchantment), + defaulted("applyDelay", IntegerArgumentType.integer(0), 1), + (ctx, targets, enchantmentRef, level) -> { + var source = ctx.getSource(); + var enchantment = enchantmentRef.value(); + + if (level > enchantment.getMaxLevel()) throw EnchantCommandAccessor.accessories$ERROR_LEVEL_TOO_HIGH().create(level, enchantment.getMaxLevel()); + + int i = 0; + + var isSingleTarget = targets.size() == 1; + + for (var entity : targets) { + if (entity instanceof LivingEntity livingEntity) { + var itemStack = livingEntity.getMainHandItem(); + if (!itemStack.isEmpty()) { + if (EnchantmentHelper.isEnchantmentCompatible(EnchantmentHelper.getEnchantmentsForCrafting(itemStack).keySet(), enchantmentRef)) { + itemStack.enchant(enchantmentRef, level); + i++; + } else if (isSingleTarget) { + throw EnchantCommandAccessor.accessories$ERROR_INCOMPATIBLE().create(itemStack.getHoverName().getString()); + } + } else if (isSingleTarget) { + throw EnchantCommandAccessor.accessories$ERROR_NO_ITEM().create(livingEntity.getName().getString()); + } + } else if (isSingleTarget) { + throw EnchantCommandAccessor.accessories$ERROR_NOT_LIVING_ENTITY().create(entity.getName().getString()); + } + } + + if (i == 0) throw EnchantCommandAccessor.accessories$ERROR_NOTHING_HAPPENED().create(); + + var fullname = Enchantment.getFullname(enchantmentRef, level); + + source.sendSuccess(() -> isSingleTarget + ? Component.translatable("commands.enchant.success.single", fullname, targets.iterator().next().getDisplayName()) + : Component.translatable("commands.enchant.success.multiple", fullname, targets.size()), true); + + return i; + } + ); + }); + root.branch("components", itemComponentBranch -> { itemComponentBranch.leaves( "effect/add", @@ -398,7 +458,7 @@ public void generateTrees(BranchedCommandGenerator root, CommandBuildContext con itemComponentBranch.leaves( "nest", - required("item", ItemArgument.item(context), (ctx, name) -> ItemArgument.getItem(ctx, name).createItemStack(1, false)), + required("item", ItemArgument.item(context), (ctx, name) -> ItemArgument.getItem(ctx, name).createItemStack(1)), (ctx, innerStack) -> { var player = ctx.getSource().getPlayerOrException(); @@ -456,7 +516,7 @@ public void generateTrees(BranchedCommandGenerator root, CommandBuildContext con itemComponentBranch.branch( "attribute", required("attribute", ResourceExtendedArgument.attributes(context)), - required("id", ResourceLocationArgument.id()), + required("id", IdentifierArgument.id()), branchBuilder -> { branchBuilder.leaves( "add", @@ -483,7 +543,7 @@ public void generateTrees(BranchedCommandGenerator root, CommandBuildContext con }); } - private static int getAttributeModifier(CommandContext ctx, Holder holder, ResourceLocation resourceLocation, double d) throws CommandSyntaxException { + private static int getAttributeModifier(CommandContext ctx, Holder holder, Identifier resourceLocation, double d) throws CommandSyntaxException { var commandSourceStack = ctx.getSource(); var livingEntity = ctx.getSource().getPlayerOrException(); @@ -513,7 +573,7 @@ private static int getAttributeModifier(CommandContext ctx, (var1, var2, var3) -> Component.translatableEscape("accessories.commands.attribute.failed.modifier_already_present_itemstack", var1, var2, var3) ); - private static int addModifier(CommandContext ctx, Holder holder, ResourceLocation resourceLocation, double d, AttributeModifier.Operation operation, String slotName, boolean isStackable, boolean usedInSlotValidation) throws CommandSyntaxException { + private static int addModifier(CommandContext ctx, Holder holder, Identifier resourceLocation, double d, AttributeModifier.Operation operation, String slotName, boolean isStackable, boolean usedInSlotValidation) throws CommandSyntaxException { var commandSourceStack = ctx.getSource(); if (operation == null) { @@ -547,7 +607,7 @@ private static int addModifier(CommandContext ctx, Holder Component.translatableEscape("accessories.commands.attribute.failed.no_modifier_itemstack", var1, var2, var3) ); - private static int removeModifier(CommandContext ctx, Holder holder, ResourceLocation location) throws CommandSyntaxException { + private static int removeModifier(CommandContext ctx, Holder holder, Identifier location) throws CommandSyntaxException { var commandSourceStack = ctx.getSource(); var livingEntity = ctx.getSource().getPlayerOrException(); @@ -597,7 +657,7 @@ private static int adjustSlotValidationOnStack(String branch, boolean addSlot, S return 1; } - private static int createRenderStack(CommandContext ctx, ResourceLocation rendererId, ResourceLocation modelId, Component component, boolean isBundle) throws CommandSyntaxException { + private static int createRenderStack(CommandContext ctx, Identifier rendererId, Identifier modelId, Component component, boolean isBundle) throws CommandSyntaxException { Item item = Items.STICK; try { @@ -618,7 +678,7 @@ private static int createRenderStack(CommandContext ctx, Res itemStack.set( AccessoriesDataComponents.SLOT_VALIDATION, - new AccessorySlotValidationComponent(Set.of("any"), Set.of()) + new AccessorySlotValidationComponent(Set.of(AccessoriesBaseData.ANY_SLOT), Set.of()) ); ctx.getSource().getPlayerOrException() diff --git a/common/src/main/java/io/wispforest/accessories/commands/AccessoriesItemCommands.java b/common/src/main/java/io/wispforest/accessories/commands/AccessoriesItemCommands.java index 6210f97e4..4c01cd56a 100644 --- a/common/src/main/java/io/wispforest/accessories/commands/AccessoriesItemCommands.java +++ b/common/src/main/java/io/wispforest/accessories/commands/AccessoriesItemCommands.java @@ -115,7 +115,7 @@ public void generateTrees(BranchedCommandGenerator generator, CommandBuildContex entityBranch .leaves( "with", - required("item", ItemArgument.item(context), (ctx, name) -> ItemArgument.getItem(ctx, name).createItemStack(1, false)), + required("item", ItemArgument.item(context), (ctx, name) -> ItemArgument.getItem(ctx, name).createItemStack(1)), defaulted("count", IntegerArgumentType.integer(1, 99), 1), (ctx, entity, slot, stack, count) -> { stack.setCount(count); @@ -211,12 +211,12 @@ private static ItemStack getEntityItem(Entity entity, Either SlotAccess slotAccess = entity.getSlot(index); - if (slotAccess == SlotAccess.NULL) throw ERROR_SOURCE_INAPPLICABLE_SLOT.create(slot); + if (slotAccess == null || slotAccess.get().isEmpty()) throw ERROR_SOURCE_INAPPLICABLE_SLOT.create(slot); return slotAccess.get().copy(); } else { if(!(entity instanceof LivingEntity livingEntity)) throw AccessoriesCommands.NON_LIVING_ENTITY_TARGET.create(); - if (livingEntity.accessoriesCapability() == null) throw AccessoriesCommands.ERROR_CAPABILITY_MISSING.create(); + if (((io.wispforest.accessories.pond.AccessoriesAPIAccess) livingEntity).accessoriesCapability() == null) throw AccessoriesCommands.ERROR_CAPABILITY_MISSING.create(); var slotPath = slot.left().get(); var reference = SlotReference.of(livingEntity, slotPath); @@ -239,7 +239,7 @@ private static int setEntityItem(CommandSourceStack source, Entity entity, Eithe SlotAccess slotAccess = entity.getSlot(index); - if (slotAccess == SlotAccess.NULL) throw ERROR_SOURCE_INAPPLICABLE_SLOT.create(slot); + if (slotAccess == null) throw ERROR_SOURCE_INAPPLICABLE_SLOT.create(slot); slotAccess.set(stack); } else { diff --git a/common/src/main/java/io/wispforest/accessories/commands/AccessoriesMixedSlotArgument.java b/common/src/main/java/io/wispforest/accessories/commands/AccessoriesMixedSlotArgument.java index 3b54a27cd..e131f933c 100644 --- a/common/src/main/java/io/wispforest/accessories/commands/AccessoriesMixedSlotArgument.java +++ b/common/src/main/java/io/wispforest/accessories/commands/AccessoriesMixedSlotArgument.java @@ -85,7 +85,7 @@ public CompletableFuture listSuggestions(CommandContext comm var entityTarget = EntityArgument.getEntity((CommandContext) commandContext, entityArgumentName); if (entityTarget instanceof LivingEntity livingEntity) { - var capability = livingEntity.accessoriesCapability(); + var capability = ((io.wispforest.accessories.pond.AccessoriesAPIAccess) livingEntity).accessoriesCapability(); if (capability != null) { suggestions.addAll( diff --git a/common/src/main/java/io/wispforest/accessories/commands/ResourceExtendedArgument.java b/common/src/main/java/io/wispforest/accessories/commands/ResourceExtendedArgument.java index 448d385d3..082fe8469 100644 --- a/common/src/main/java/io/wispforest/accessories/commands/ResourceExtendedArgument.java +++ b/common/src/main/java/io/wispforest/accessories/commands/ResourceExtendedArgument.java @@ -22,7 +22,7 @@ import net.minecraft.core.registries.Registries; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceKey; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.world.entity.ai.attributes.Attribute; import org.jetbrains.annotations.Nullable; @@ -51,10 +51,10 @@ public class ResourceExtendedArgument implements ArgumentType> { final ResourceKey> registryKey; private final HolderLookup registryLookup; - private final Function> additionalLookup; - private final Supplier> additionalSuggestions; + private final Function> additionalLookup; + private final Supplier> additionalSuggestions; - public ResourceExtendedArgument(CommandBuildContext context, ResourceKey> registryKey, Function> additionalLookup, Supplier> additionalSuggestions) { + public ResourceExtendedArgument(CommandBuildContext context, ResourceKey> registryKey, Function> additionalLookup, Supplier> additionalSuggestions) { this.registryKey = registryKey; this.registryLookup = context.lookupOrThrow(registryKey); @@ -62,7 +62,7 @@ public ResourceExtendedArgument(CommandBuildContext context, ResourceKey ResourceExtendedArgument resource(CommandBuildContext context, ResourceKey> registryKey, Function> additionalLookup, Supplier> additionalSuggestions) { + public static ResourceExtendedArgument resource(CommandBuildContext context, ResourceKey> registryKey, Function> additionalLookup, Supplier> additionalSuggestions) { return new ResourceExtendedArgument<>(context, registryKey, additionalLookup, additionalSuggestions); } @@ -94,19 +94,19 @@ public static Holder getResource(CommandContext conte } public Holder parse(StringReader builder) throws CommandSyntaxException { - ResourceLocation resourceLocation = ResourceLocation.read(builder); + Identifier resourceLocation = Identifier.read(builder); ResourceKey resourceKey = ResourceKey.create(this.registryKey, resourceLocation); var entry = this.registryLookup.get(resourceKey) .map(tReference -> (Holder) tReference) .or(() -> Optional.ofNullable(this.additionalLookup.apply(resourceLocation))); - return entry.orElseThrow(() -> ERROR_UNKNOWN_RESOURCE.createWithContext(builder, resourceLocation, this.registryKey.location())); + return entry.orElseThrow(() -> ERROR_UNKNOWN_RESOURCE.createWithContext(builder, resourceLocation, this.registryKey.identifier())); } @Override public CompletableFuture listSuggestions(CommandContext commandContext, SuggestionsBuilder suggestionsBuilder) { - var registryKeys = this.registryLookup.listElementIds().map(ResourceKey::location); + var registryKeys = this.registryLookup.listElementIds().map(ResourceKey::identifier); var extraEntries = this.additionalSuggestions.get(); return SharedSuggestionProvider.suggestResource(Stream.concat(registryKeys, extraEntries), suggestionsBuilder); diff --git a/common/src/main/java/io/wispforest/accessories/commands/SlotArgumentType.java b/common/src/main/java/io/wispforest/accessories/commands/SlotArgumentType.java index 73e94fb09..d974f7741 100644 --- a/common/src/main/java/io/wispforest/accessories/commands/SlotArgumentType.java +++ b/common/src/main/java/io/wispforest/accessories/commands/SlotArgumentType.java @@ -6,11 +6,12 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.suggestion.Suggestions; import com.mojang.brigadier.suggestion.SuggestionsBuilder; +import io.wispforest.accessories.api.data.AccessoriesBaseData; import io.wispforest.accessories.api.slot.SlotType; import io.wispforest.accessories.data.SlotTypeLoader; import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.SharedSuggestionProvider; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import java.util.ArrayList; import java.util.concurrent.CompletableFuture; @@ -25,11 +26,11 @@ public static String getSlot(CommandContext context, String @Override public String parse(StringReader reader) throws CommandSyntaxException { - ResourceLocation arg = ResourceLocation.read(reader); + Identifier arg = Identifier.read(reader); String slotName = (arg.getNamespace().equals("minecraft")) ? arg.getPath() : arg.toString(); - if (slotName.equals("any")) return "any"; + if (slotName.equals(AccessoriesBaseData.ANY_SLOT)) return AccessoriesBaseData.ANY_SLOT; var slotType = SlotTypeLoader.INSTANCE.getSlotType(false, slotName); @@ -47,7 +48,7 @@ public CompletableFuture listSuggestions(CommandContext cont var validSlots = new ArrayList<>(SlotTypeLoader.INSTANCE.getEntries(false).values().stream().map(SlotType::name).toList()); - validSlots.addFirst("any"); + validSlots.addFirst(AccessoriesBaseData.ANY_SLOT); return SharedSuggestionProvider.suggest(validSlots, builder); } diff --git a/common/src/main/java/io/wispforest/accessories/commands/api/ArgumentRegistrationCallback.java b/common/src/main/java/io/wispforest/accessories/commands/api/ArgumentRegistrationCallback.java index 28da5347b..eacee4c14 100644 --- a/common/src/main/java/io/wispforest/accessories/commands/api/ArgumentRegistrationCallback.java +++ b/common/src/main/java/io/wispforest/accessories/commands/api/ArgumentRegistrationCallback.java @@ -2,8 +2,8 @@ import com.mojang.brigadier.arguments.ArgumentType; import io.wispforest.accessories.commands.api.core.RecordArgumentTypeInfo; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; public interface ArgumentRegistrationCallback { - , T> RecordArgumentTypeInfo register(ResourceLocation location, Class clazz, RecordArgumentTypeInfo info); + , T> RecordArgumentTypeInfo register(Identifier location, Class clazz, RecordArgumentTypeInfo info); } diff --git a/common/src/main/java/io/wispforest/accessories/compat/config/AccessoriesConfigModel.java b/common/src/main/java/io/wispforest/accessories/compat/config/AccessoriesConfigModel.java index a9a2eae7e..9f83f096b 100644 --- a/common/src/main/java/io/wispforest/accessories/compat/config/AccessoriesConfigModel.java +++ b/common/src/main/java/io/wispforest/accessories/compat/config/AccessoriesConfigModel.java @@ -6,7 +6,7 @@ import io.wispforest.accessories.impl.option.AccessoriesPlayerOptionsHolder; import io.wispforest.owo.config.Option; import io.wispforest.owo.config.annotation.*; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; @@ -72,9 +72,9 @@ public static class ScreenOptions { @Hook public List menuButtonInjections = new ArrayList<>( List.of( - new MenuButtonInjection(ResourceLocation.withDefaultNamespace("creative_player_inventory"), 96, 6), - new MenuButtonInjection(ResourceLocation.withDefaultNamespace("player_inventory"), 66, 8), - new MenuButtonInjection(ResourceLocation.withDefaultNamespace("horse_inventory"), 69, 18) + new MenuButtonInjection(Identifier.withDefaultNamespace("creative_player_inventory"), 96, 6), + new MenuButtonInjection(Identifier.withDefaultNamespace("player_inventory"), 66, 8), + new MenuButtonInjection(Identifier.withDefaultNamespace("horse_inventory"), 69, 18) ) ); @@ -107,6 +107,12 @@ public static class ScreenOptions { @Hook public boolean alwaysShowCraftingGrid = false; + @Hook + public TooltipInfoType equipCheckTooltipType = TooltipInfoType.BASIC; + + @Hook + public boolean showSlotDarkeningEffect = true; + // Screen Injected Button offsets @SectionHeader("hover") diff --git a/common/src/main/java/io/wispforest/accessories/compat/config/MenuButtonInjection.java b/common/src/main/java/io/wispforest/accessories/compat/config/MenuButtonInjection.java index 35f766bb0..01673ff13 100644 --- a/common/src/main/java/io/wispforest/accessories/compat/config/MenuButtonInjection.java +++ b/common/src/main/java/io/wispforest/accessories/compat/config/MenuButtonInjection.java @@ -1,33 +1,33 @@ package io.wispforest.accessories.compat.config; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import java.util.Objects; public final class MenuButtonInjection { - public ResourceLocation menuType; + public Identifier menuType; public int xOffset; public int yOffset; public MenuButtonInjection() { - this.menuType = ResourceLocation.fromNamespaceAndPath("minecraft", ""); + this.menuType = Identifier.fromNamespaceAndPath("minecraft", ""); this.xOffset = 0; this.yOffset = 0; } @Deprecated - public MenuButtonInjection(ResourceLocation menuType, int xOffset, int yOffset, boolean mini) { + public MenuButtonInjection(Identifier menuType, int xOffset, int yOffset, boolean mini) { this(menuType, xOffset, yOffset); } - public MenuButtonInjection(ResourceLocation menuType, int xOffset, int yOffset) { + public MenuButtonInjection(Identifier menuType, int xOffset, int yOffset) { this.menuType = menuType; this.xOffset = xOffset; this.yOffset = yOffset; } - public ResourceLocation menuType() { + public Identifier menuType() { return menuType; } diff --git a/common/src/main/java/io/wispforest/accessories/compat/config/TooltipInfoType.java b/common/src/main/java/io/wispforest/accessories/compat/config/TooltipInfoType.java new file mode 100644 index 000000000..91d934936 --- /dev/null +++ b/common/src/main/java/io/wispforest/accessories/compat/config/TooltipInfoType.java @@ -0,0 +1,8 @@ +package io.wispforest.accessories.compat.config; + +public enum TooltipInfoType { + ALL, + ADVANCED, + BASIC, + DISABLED +} diff --git a/common/src/main/java/io/wispforest/accessories/compat/config/client/components/ConfigurableStructLayout.java b/common/src/main/java/io/wispforest/accessories/compat/config/client/components/ConfigurableStructLayout.java index 138f32c00..43673a16e 100644 --- a/common/src/main/java/io/wispforest/accessories/compat/config/client/components/ConfigurableStructLayout.java +++ b/common/src/main/java/io/wispforest/accessories/compat/config/client/components/ConfigurableStructLayout.java @@ -7,14 +7,14 @@ import io.wispforest.owo.ui.component.ButtonComponent; import io.wispforest.owo.ui.component.LabelComponent; import io.wispforest.owo.ui.container.FlowLayout; -import io.wispforest.owo.ui.core.Component; -import io.wispforest.owo.ui.core.ParentComponent; +import io.wispforest.owo.ui.core.UIComponent; +import io.wispforest.owo.ui.core.ParentUIComponent; import io.wispforest.owo.ui.core.Positioning; import io.wispforest.owo.ui.core.Sizing; import io.wispforest.owo.ui.parsing.UIModel; import io.wispforest.owo.util.NumberReflection; import io.wispforest.owo.util.Observable; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import org.apache.commons.lang3.mutable.MutableBoolean; import org.apache.commons.lang3.mutable.MutableObject; @@ -50,7 +50,7 @@ protected ConfigurableStructLayout(Sizing horizontalSizing, Sizing verticalSizin protected ConfigurableStructLayout build(T value) { handlers.forEach((field, handler) -> { - var component = new MutableObject(); + var component = new MutableObject(); var name = field.getName(); var translationKey = "text.config." + configName + ".option." + optionKey.asString() + "." + name; @@ -71,7 +71,7 @@ public ConfigurableStructLayout composeComponents(Class clazz, List this.numberField(field, ReflectOps.get(field, value)); } else if (fieldClazz == String.class) { this.stringField(field, ReflectOps.get(field, value)); - } else if (fieldClazz == ResourceLocation.class) { + } else if (fieldClazz == Identifier.class) { this.identifierField(field, ReflectOps.get(field, value)); } else if (fieldClazz.isEnum()) { this.createEnumButton(field, ReflectOps.get(field, value)); @@ -114,11 +114,11 @@ public ConfigurableStructLayout stringField(Field field, String defaultValue) }); } - public ConfigurableStructLayout identifierField(Field field, ResourceLocation defaultValue) { + public ConfigurableStructLayout identifierField(Field field, Identifier defaultValue) { return textBoxHandle(field, defaultValue, configTextBox -> { configTextBox.inputPredicate(s -> s.matches("[a-z0-9_.:\\-]*")); - configTextBox.applyPredicate(s -> ResourceLocation.tryParse(s) != null); - configTextBox.valueParser(ResourceLocation::parse); + configTextBox.applyPredicate(s -> Identifier.tryParse(s) != null); + configTextBox.valueParser(Identifier::parse); }); } @@ -185,7 +185,7 @@ public ConfigurableStructLayout rangeControlsHandle(Field // ------------------------------------ var sliderControls = optionComponent.childById(FlowLayout.class, "slider-controls"); - var textControls = (ParentComponent) textBoxFactory(defaultValue, Objects::toString, configTextBox -> { + var textControls = (ParentUIComponent) textBoxFactory(defaultValue, Objects::toString, configTextBox -> { configTextBox.configureForNumber(clazz); var predicate = configTextBox.applyPredicate(); @@ -281,7 +281,7 @@ private ComponentFactory textBoxFactory(F defaultValue, Function> ConfigurableStructLayout createEnumButton(Field field, F defaultValue) { var factory = new ComponentFactory() { @Override - public Component createComponent(T t, Field field, Function getter, BiConsumer setter, String translationKey, ParentComponent parentComponent) { + public UIComponent createComponent(T t, Field field, Function getter, BiConsumer setter, String translationKey, ParentUIComponent parentComponent) { var optionComponent = model.expandTemplate(FlowLayout.class, "enum-config-option", OptionComponents.packParameters(translationKey, getter.apply(t).toString()) @@ -338,7 +338,7 @@ public Component createComponent(T t, Field field, Function getter, BiCons public ConfigurableStructLayout createBooleanButton(Field field, Boolean defaultValue) { var factory = new ComponentFactory() { @Override - public Component createComponent(T t, Field field, Function getter, BiConsumer setter, String translationKey, ParentComponent parentComponent) { + public UIComponent createComponent(T t, Field field, Function getter, BiConsumer setter, String translationKey, ParentUIComponent parentComponent) { FlowLayout optionComponent = model.expandTemplate(FlowLayout.class, "boolean-toggle-config-option", OptionComponents.packParameters(translationKey, getter.apply(t).toString()) @@ -388,7 +388,7 @@ public Component createComponent(T t, Field field, Function getter, } public interface ComponentFactory { - Component createComponent(T t, Field field, Function getter, BiConsumer setter, String translation, ParentComponent parentComponent); + UIComponent createComponent(T t, Field field, Function getter, BiConsumer setter, String translation, ParentUIComponent parentComponent); } static class ReflectOps { diff --git a/common/src/main/java/io/wispforest/accessories/compat/config/client/components/StructListOptionContainer.java b/common/src/main/java/io/wispforest/accessories/compat/config/client/components/StructListOptionContainer.java index 4e2008f32..559b0c0f6 100644 --- a/common/src/main/java/io/wispforest/accessories/compat/config/client/components/StructListOptionContainer.java +++ b/common/src/main/java/io/wispforest/accessories/compat/config/client/components/StructListOptionContainer.java @@ -4,8 +4,8 @@ import io.wispforest.owo.config.Option; import io.wispforest.owo.config.ui.component.ListOptionContainer; import io.wispforest.owo.ops.TextOps; -import io.wispforest.owo.ui.component.Components; -import io.wispforest.owo.ui.container.Containers; +import io.wispforest.owo.ui.component.UIComponents; +import io.wispforest.owo.ui.container.UIContainers; import io.wispforest.owo.ui.container.FlowLayout; import io.wispforest.owo.ui.core.CursorStyle; import io.wispforest.owo.ui.core.Insets; @@ -36,11 +36,11 @@ protected void refreshOptions() { var listType = (Class) ReflectionUtils.getTypeArgument(this.backingOption.backingField().field().getGenericType(), 0); for (int i = 0; i < this.backingList.size(); i++) { - var container = Containers.horizontalFlow(Sizing.fill(100), Sizing.content()); + var container = UIContainers.horizontalFlow(Sizing.fill(100), Sizing.content()); container.verticalAlignment(VerticalAlignment.CENTER); int optionIndex = i; - final var label = Components.label(TextOps.withFormatting("- ", ChatFormatting.GRAY)); + final var label = UIComponents.label(TextOps.withFormatting("- ", ChatFormatting.GRAY)); label.margins(Insets.left(6)); //10 @@ -64,7 +64,7 @@ protected void refreshOptions() { backingList.set(i, (T) ConfigurableStructLayout.ReflectOps.defaultConstruct(listType)); } - var labelContainer = Containers.verticalFlow(Sizing.fixed(19), Sizing.content()); + var labelContainer = UIContainers.verticalFlow(Sizing.fixed(19), Sizing.content()); labelContainer.child(label); diff --git a/common/src/main/java/io/wispforest/accessories/compat/jei/AccessoriesClientJEIPlugin.java b/common/src/main/java/io/wispforest/accessories/compat/jei/AccessoriesClientJEIPlugin.java index 1686d7f4b..7d418de9e 100644 --- a/common/src/main/java/io/wispforest/accessories/compat/jei/AccessoriesClientJEIPlugin.java +++ b/common/src/main/java/io/wispforest/accessories/compat/jei/AccessoriesClientJEIPlugin.java @@ -1,5 +1,9 @@ package io.wispforest.accessories.compat.jei; +// JEI integration disabled - no JEI available for 1.21.11 yet +// TODO: Re-enable when JEI is updated for 1.21.11 + +/* import io.wispforest.accessories.Accessories; import io.wispforest.accessories.client.gui.AccessoriesScreen; import mezz.jei.api.IModPlugin; @@ -7,14 +11,14 @@ import mezz.jei.api.gui.handlers.IGuiContainerHandler; import mezz.jei.api.registration.IGuiHandlerRegistration; import net.minecraft.client.renderer.Rect2i; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import java.util.List; @JeiPlugin public class AccessoriesClientJEIPlugin implements IModPlugin { @Override - public ResourceLocation getPluginUid() { + public Identifier getPluginUid() { return Accessories.of("main"); } @@ -30,3 +34,4 @@ public List getGuiExtraAreas(AccessoriesScreen screen) { }); } } +*/ diff --git a/common/src/main/java/io/wispforest/accessories/criteria/AccessoryChangedCriterion.java b/common/src/main/java/io/wispforest/accessories/criteria/AccessoryChangedCriterion.java index 6c6f41797..34ca7d454 100644 --- a/common/src/main/java/io/wispforest/accessories/criteria/AccessoryChangedCriterion.java +++ b/common/src/main/java/io/wispforest/accessories/criteria/AccessoryChangedCriterion.java @@ -4,10 +4,10 @@ import com.mojang.serialization.codecs.RecordCodecBuilder; import io.wispforest.accessories.api.slot.SlotPath; import io.wispforest.accessories.data.SlotGroupLoader; -import net.minecraft.advancements.critereon.ContextAwarePredicate; -import net.minecraft.advancements.critereon.EntityPredicate; -import net.minecraft.advancements.critereon.ItemPredicate; -import net.minecraft.advancements.critereon.SimpleCriterionTrigger; +import net.minecraft.advancements.criterion.ContextAwarePredicate; +import net.minecraft.advancements.criterion.EntityPredicate; +import net.minecraft.advancements.criterion.ItemPredicate; +import net.minecraft.advancements.criterion.SimpleCriterionTrigger; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.item.ItemStack; import org.jetbrains.annotations.NotNull; diff --git a/common/src/main/java/io/wispforest/accessories/data/CustomRendererLoader.java b/common/src/main/java/io/wispforest/accessories/data/CustomRendererLoader.java index b5145f6d6..c7c50d3f7 100644 --- a/common/src/main/java/io/wispforest/accessories/data/CustomRendererLoader.java +++ b/common/src/main/java/io/wispforest/accessories/data/CustomRendererLoader.java @@ -18,7 +18,7 @@ import io.wispforest.owo.Owo; import net.minecraft.client.Minecraft; import net.minecraft.resources.FileToIdConverter; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.server.MinecraftServer; import net.minecraft.server.packs.PackType; import net.minecraft.server.packs.resources.ResourceManager; @@ -40,7 +40,7 @@ public class CustomRendererLoader extends SimpleManagedEndecDataLoader missingRenderersClient = new HashSet<>(); - private final Set missingRenderersServer = new HashSet<>(); + private final Set missingRenderersClient = new HashSet<>(); + private final Set missingRenderersServer = new HashSet<>(); @Override protected void onSync() { @@ -95,7 +95,7 @@ protected void onSync() { } @Override - public Map mapFrom(Map rawData) { + public Map mapFrom(Map rawData) { this.resolvedServer.clear(); this.missingRenderersServer.clear(); @@ -104,7 +104,7 @@ public Map mapFrom(Map currentResolveTree = new ArrayDeque<>(); + Deque currentResolveTree = new ArrayDeque<>(); var references = new HashMap<>(deferredRenderer.references()); RenderingFunction.Compound function = null; @@ -133,7 +133,7 @@ private RenderingFunction.Compound getOrResolveRendererInitial(DeferredRenderer return function; } - private RenderingFunction.Compound resolveRenderer(Deque currentResolveTree, ResourceLocation id, Map references, boolean isClientSide, boolean allowMissing) { + private RenderingFunction.Compound resolveRenderer(Deque currentResolveTree, Identifier id, Map references, boolean isClientSide, boolean allowMissing) { currentResolveTree.push(id); RawRenderer rawRenderer = null; @@ -163,7 +163,7 @@ private RenderingFunction.Compound resolveRenderer(Deque curre } @Nullable - private RenderingFunction.Compound resolveRawData(Deque currentResolveTree, ResourceLocation id, RenderingFunction function, Map references, boolean isClientSide) { + private RenderingFunction.Compound resolveRawData(Deque currentResolveTree, Identifier id, RenderingFunction function, Map references, boolean isClientSide) { if (function instanceof RawRenderer data) { data.references().forEach(references::putIfAbsent); @@ -276,7 +276,7 @@ private static void resolveReferences(Map references, JsonE //-- @ApiStatus.Internal - public static void constantFileResolving(MinecraftServer server, ResourceLocation id) { + public static void constantFileResolving(MinecraftServer server, Identifier id) { if (server.isDedicatedServer() && Accessories.DEBUG) return; PRIMARY.constantResolveTarget = id; @@ -287,7 +287,7 @@ public static boolean isConstantResolveTarget() { } @Nullable - protected RenderingFunction.RawRenderer getDataFromId(ResourceLocation id, boolean isClientSide) { + protected RenderingFunction.RawRenderer getDataFromId(Identifier id, boolean isClientSide) { var fileId = FileToIdConverter.json(this.type).idToFile(id); ResourceManager resource = getResourceManager(isClientSide); @@ -321,7 +321,7 @@ protected RenderingFunction.RawRenderer getDataFromId(ResourceLocation id, boole return null; } - private static final Cache ERROR_CACHE = CacheBuilder.newBuilder() + private static final Cache ERROR_CACHE = CacheBuilder.newBuilder() .expireAfterAccess(Duration.ofSeconds(30)) .maximumSize(3000) .build(); @@ -338,7 +338,7 @@ private void minimalErroring(Throwable throwable) { LOGGER.error(throwable.getMessage()); } - private void errorIfDifferent(ResourceLocation id, Throwable e, Runnable runnable) { + private void errorIfDifferent(Identifier id, Throwable e, Runnable runnable) { if (!alwaysResolveFlag) { runnable.run(); return; diff --git a/common/src/main/java/io/wispforest/accessories/data/EntitySlotLoader.java b/common/src/main/java/io/wispforest/accessories/data/EntitySlotLoader.java index 0bcf65638..5bbd3e860 100644 --- a/common/src/main/java/io/wispforest/accessories/data/EntitySlotLoader.java +++ b/common/src/main/java/io/wispforest/accessories/data/EntitySlotLoader.java @@ -18,7 +18,7 @@ import net.minecraft.core.Holder; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.core.registries.Registries; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.server.packs.PackType; import net.minecraft.server.packs.resources.ResourceManager; import net.minecraft.tags.TagKey; @@ -35,7 +35,7 @@ /** * Resource Reload in which handles the loading of {@link SlotType}'s bindings - * to the targeted {@link EntityType} though a {@link TagKey} or {@link ResourceLocation} + * to the targeted {@link EntityType} though a {@link TagKey} or {@link Identifier} */ public class EntitySlotLoader extends EndecDataLoader implements SyncedDataHelper, List>> { @@ -98,7 +98,7 @@ public record RawEnityBinding(Set entityTargets, Set slotTypes) @Override public Endec, List>> syncDataEndec() { return Endec.map(LinkedHashMap::new, - type -> BuiltInRegistries.ENTITY_TYPE.getKey(type).toString(), strType -> BuiltInRegistries.ENTITY_TYPE.getValue(ResourceLocation.parse(strType)), + type -> BuiltInRegistries.ENTITY_TYPE.getKey(type).toString(), strType -> BuiltInRegistries.ENTITY_TYPE.getValue(Identifier.parse(strType)), Endec.STRING.listOf()); } @@ -108,8 +108,9 @@ public void onReceivedData(SequencedMap, List> data) { for (var entry : data.entrySet()) { var map = entry.getValue().stream() - .map(string -> SlotTypeLoader.INSTANCE.getSlotType(true, string)) - .collect(CollectionUtils.toLinkedMap(SlotType::name)); + .map(string -> SlotTypeLoader.INSTANCE.getSlotType(true, string)) + .filter(Objects::nonNull) + .collect(CollectionUtils.linkedMapKeyCollector(SlotType::name)); entitySlotTypes.put(entry.getKey(), map); } @@ -167,7 +168,7 @@ public void buildEntryMap() { //-- @Override - protected void apply(Map rawData, ResourceManager resourceManager, ProfilerFiller profiler) { + protected void apply(Map rawData, ResourceManager resourceManager, ProfilerFiller profiler) { var allSlotTypes = SlotTypeLoader.INSTANCE.getEntries(false); this.tagToBoundSlots.clear(); @@ -199,14 +200,14 @@ protected void apply(Map rawData, ResourceMan rawEnityBinding.entityTargets().forEach(string -> { if(string.contains("#")){ - var entityTypeTagLocation = ResourceLocation.tryParse(string.replace("#", "")); + var entityTypeTagLocation = Identifier.tryParse(string.replace("#", "")); var entityTypeTag = TagKey.create(Registries.ENTITY_TYPE, entityTypeTagLocation); tagToBoundSlots.computeIfAbsent(entityTypeTag, entityTag -> new HashMap<>()) .putAll(slots); } else { - Optional.ofNullable(ResourceLocation.tryParse(string)) + Optional.ofNullable(Identifier.tryParse(string)) .flatMap(BuiltInRegistries.ENTITY_TYPE::getOptional) .ifPresentOrElse(entityType -> { entityToBoundSlots.computeIfAbsent(entityType, entityType1 -> new HashMap<>()) diff --git a/common/src/main/java/io/wispforest/accessories/data/RendererBindingLoader.java b/common/src/main/java/io/wispforest/accessories/data/RendererBindingLoader.java index 9b018b00a..60cd1bf61 100644 --- a/common/src/main/java/io/wispforest/accessories/data/RendererBindingLoader.java +++ b/common/src/main/java/io/wispforest/accessories/data/RendererBindingLoader.java @@ -6,7 +6,7 @@ import io.wispforest.endec.Endec; import io.wispforest.owo.serialization.endec.MinecraftEndecs; import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.server.packs.PackType; import net.minecraft.server.packs.resources.ResourceManager; import net.minecraft.util.profiling.ProfilerFiller; @@ -14,19 +14,19 @@ import java.util.Map; -public class RendererBindingLoader extends EndecDataLoader> { +public class RendererBindingLoader extends EndecDataLoader> { public static final RendererBindingLoader LOADER = new RendererBindingLoader(); private RendererBindingLoader() { super(Accessories.of("rendering_binding"), "accessories/render/binding", Endec.map( item -> BuiltInRegistries.ITEM.getKey(item).toString(), - itemId -> BuiltInRegistries.ITEM.getValue(ResourceLocation.parse(itemId)), + itemId -> BuiltInRegistries.ITEM.getValue(Identifier.parse(itemId)), MinecraftEndecs.IDENTIFIER), PackType.CLIENT_RESOURCES); } @Override - protected void apply(Map> rawData, ResourceManager resourceManager, ProfilerFiller profiler) { + protected void apply(Map> rawData, ResourceManager resourceManager, ProfilerFiller profiler) { rawData.forEach((location, data) -> AccessoriesRendererRegistry.setDataLoadedItemToRenderer(data)); } } diff --git a/common/src/main/java/io/wispforest/accessories/data/SlotGroupLoader.java b/common/src/main/java/io/wispforest/accessories/data/SlotGroupLoader.java index 770596e5b..bb232a2bd 100644 --- a/common/src/main/java/io/wispforest/accessories/data/SlotGroupLoader.java +++ b/common/src/main/java/io/wispforest/accessories/data/SlotGroupLoader.java @@ -2,6 +2,7 @@ import com.mojang.logging.LogUtils; import io.wispforest.accessories.Accessories; +import io.wispforest.accessories.api.data.AccessoriesBaseData; import io.wispforest.accessories.api.slot.SlotGroup; import io.wispforest.accessories.api.slot.SlotType; import io.wispforest.accessories.api.slot.UniqueSlotHandling; @@ -17,7 +18,7 @@ import io.wispforest.endec.StructEndec; import io.wispforest.endec.impl.StructEndecBuilder; import io.wispforest.owo.serialization.endec.MinecraftEndecs; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.server.packs.PackType; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.level.Level; @@ -82,7 +83,7 @@ public static Map> getValidGroups(LivingEntity living) return slots.isEmpty() ? null : Map.entry(slotGroup, slots); }) .filter(Objects::nonNull) - .collect(CollectionUtils.toLinkedMap()); + .collect(CollectionUtils.linkedMapCollector()); } public static Optional getGroup(Level level, String group){ @@ -118,10 +119,10 @@ public final SlotGroup getOrDefaultGroup(boolean isClientSide, String slot){ if(entry.slots().contains(slot)) return entry; } - return groups.get(Accessories.parseLocationOrDefault("any")); + return groups.get(Accessories.parseLocationOrDefault(AccessoriesBaseData.ANY_SLOT)); } - public record RawGroupData(int order, Set slots, ResourceLocation icon) { + public record RawGroupData(int order, Set slots, Identifier icon) { public static final StructEndec ENDEC = StructEndecBuilder.of( Endec.INT.fieldOf("order", RawGroupData::order), EndecUtils., String>collectionOf(Endec.STRING, LinkedHashSet::new).fieldOf("slots", RawGroupData::slots), @@ -131,7 +132,7 @@ public record RawGroupData(int order, Set slots, ResourceLocation icon) } @Override - public Map mapFrom(Map rawData) { + public Map mapFrom(Map rawData) { var slotGroups = new LinkedHashMap(); slotGroups.put("unsorted", new SlotGroupBuilder("unsorted").order(30)); @@ -143,8 +144,8 @@ public Map mapFrom(Map { var pathParts = location.getPath().split("/"); - String groupName = pathParts[pathParts.length - 1]; - String namespace = pathParts.length > 1 ? pathParts[0] + ":" : ""; + var groupName = pathParts[pathParts.length - 1]; + var namespace = pathParts.length > 1 ? pathParts[0] + ":" : ""; var isShared = namespace.isBlank(); @@ -153,26 +154,31 @@ public Map mapFrom(Map mapFrom(Map Map.entry(Accessories.parseLocationOrDefault(entry.getKey()), entry.getValue().build())) - .sorted(Map.Entry.comparingByValue().reversed()) - .collect(CollectionUtils.toLinkedMap()); + .sorted(Map.Entry.comparingByValue().reversed()) + .collect(CollectionUtils.linkedMapCollector()); } public static class SlotGroupBuilder { @@ -211,7 +217,7 @@ public static class SlotGroupBuilder { private Integer order = null; private final Set slots = new HashSet<>(); - private ResourceLocation iconLocation = SlotGroup.UNKNOWN; + private Identifier iconLocation = SlotGroup.UNKNOWN; public SlotGroupBuilder(String name){ this.name = name; @@ -235,7 +241,7 @@ public SlotGroupBuilder addSlots(Collection values){ return this; } - public SlotGroupBuilder icon(ResourceLocation location) { + public SlotGroupBuilder icon(Identifier location) { this.iconLocation = location; return this; diff --git a/common/src/main/java/io/wispforest/accessories/data/SlotTypeLoader.java b/common/src/main/java/io/wispforest/accessories/data/SlotTypeLoader.java index c30678675..bbfc8423d 100644 --- a/common/src/main/java/io/wispforest/accessories/data/SlotTypeLoader.java +++ b/common/src/main/java/io/wispforest/accessories/data/SlotTypeLoader.java @@ -2,10 +2,11 @@ import com.mojang.logging.LogUtils; import io.wispforest.accessories.Accessories; +import io.wispforest.accessories.api.data.AccessoriesBaseData; import io.wispforest.accessories.api.events.DropRule; -import io.wispforest.accessories.api.slot.SlotPredicateRegistry; import io.wispforest.accessories.api.slot.SlotType; import io.wispforest.accessories.api.slot.UniqueSlotHandling; +import io.wispforest.accessories.api.slot.validator.SlotValidatorRegistry; import io.wispforest.accessories.data.api.ManagedEndecDataLoader; import io.wispforest.accessories.impl.slot.ExtraSlotTypeProperties; import io.wispforest.accessories.impl.slot.SlotTypeImpl; @@ -17,7 +18,7 @@ import io.wispforest.endec.impl.StructEndecBuilder; import io.wispforest.owo.serialization.endec.MinecraftEndecs; import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.server.packs.PackType; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.LivingEntity; @@ -81,7 +82,7 @@ public static Collection getUsedSlotsByRegistryItem(LivingEntity livin BuiltInRegistries.ITEM.forEach(item -> { var stack = item.getDefaultInstance(); - var validSlots = SlotPredicateRegistry.getStackSlotTypes(living, stack); + var validSlots = SlotValidatorRegistry.getStackSlotTypes(living, stack); validSlotTypes.addAll(validSlots); }); @@ -99,7 +100,7 @@ protected void onSync() { } @Override - public Map mapFrom(Map rawData) { + public Map mapFrom(Map rawData) { var uniqueSlots = new LinkedHashMap(); try { @@ -177,7 +178,7 @@ public Map mapFrom(Map(); + var tempMap = new HashMap(); for (var modifier : Accessories.config().modifiers()) { var builder = builders.getOrDefault(modifier.slotType, null); @@ -188,7 +189,7 @@ public Map mapFrom(Map { - if(s.equals("any")) return; + if(s.equals(AccessoriesBaseData.ANY_SLOT)) return; tempMap.put(Accessories.parseLocationOrDefault(s), slotBuilder.create()); }); @@ -198,11 +199,11 @@ public Map mapFrom(Map validators, + @Nullable Set validators, @Nullable DropRule dropRule) { public static final StructEndec ENDEC = StructEndecBuilder.of( MinecraftEndecs.IDENTIFIER.optionalFieldOf("icon", RawSlotData::icon, () -> null), @@ -217,13 +218,13 @@ public record RawSlotData(@Nullable ResourceLocation icon, public static class SlotBuilder { private final String name; - private ResourceLocation icon = null; + private Identifier icon = null; private Integer order = null; public Integer baseAmount = null; private Integer offsetAmount = 0; - private final Set validators = new HashSet<>(); + private final Set validators = new HashSet<>(); private DropRule dropRule = null; private Optional alternativeTranslation = Optional.empty(); @@ -237,7 +238,7 @@ public SlotBuilder alternativeTranslation(String value){ return this; } - public SlotBuilder icon(ResourceLocation value){ + public SlotBuilder icon(Identifier value){ if (value != null) this.icon = value; return this; } @@ -262,7 +263,7 @@ public SlotBuilder subtractAmount(int value){ return this; } - public SlotBuilder validator(ResourceLocation validator){ + public SlotBuilder validator(Identifier validator){ this.validators.add(validator); return this; } diff --git a/common/src/main/java/io/wispforest/accessories/data/api/EndecDataLoader.java b/common/src/main/java/io/wispforest/accessories/data/api/EndecDataLoader.java index c7a5e8fd5..128cd976a 100644 --- a/common/src/main/java/io/wispforest/accessories/data/api/EndecDataLoader.java +++ b/common/src/main/java/io/wispforest/accessories/data/api/EndecDataLoader.java @@ -12,7 +12,7 @@ import net.minecraft.core.HolderLookup; import net.minecraft.resources.FileToIdConverter; import net.minecraft.resources.RegistryOps; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.server.packs.PackType; import net.minecraft.server.packs.resources.PreparableReloadListener; import net.minecraft.server.packs.resources.ResourceManager; @@ -32,10 +32,10 @@ public abstract class EndecDataLoader extends SimpleJsonResourceReloadListene protected final String type; - protected final ResourceLocation id; + protected final Identifier id; protected final Endec endec; - protected final Set dependencies; + protected final Set dependencies; protected final SerializationContext context; @@ -43,23 +43,23 @@ public abstract class EndecDataLoader extends SimpleJsonResourceReloadListene private Function registriesAccess = sharedState -> null; - protected EndecDataLoader(ResourceLocation id, String type, Endec endec, PackType packType) { + protected EndecDataLoader(Identifier id, String type, Endec endec, PackType packType) { this(id, type, endec, packType, false); } - protected EndecDataLoader(ResourceLocation id, String type, Endec endec, PackType packType, Set value) { + protected EndecDataLoader(Identifier id, String type, Endec endec, PackType packType, Set value) { this(id, type, endec, packType, SerializationContext.empty(),false, value); } - protected EndecDataLoader(ResourceLocation id, String type, Endec endec, PackType packType, boolean requiresRegistries) { + protected EndecDataLoader(Identifier id, String type, Endec endec, PackType packType, boolean requiresRegistries) { this(id, type, endec, packType, SerializationContext.empty(), requiresRegistries); } - protected EndecDataLoader(ResourceLocation id, String type, Endec endec, PackType packType, SerializationContext context, boolean requiresRegistries) { + protected EndecDataLoader(Identifier id, String type, Endec endec, PackType packType, SerializationContext context, boolean requiresRegistries) { this(id, type, endec, packType, context, requiresRegistries, Set.of()); } - protected EndecDataLoader(ResourceLocation id, String type, Endec endec, PackType packType, SerializationContext context, boolean requiresRegistries, Set value) { + protected EndecDataLoader(Identifier id, String type, Endec endec, PackType packType, SerializationContext context, boolean requiresRegistries, Set value) { super(new DelegatingCodec<>(endec.toString(), endec), FileToIdConverter.json(type)); this.id = id; @@ -81,12 +81,12 @@ public void setRegistriesAccess(Function getDependencyIds() { + public Set getDependencyIds() { return this.dependencies; } @@ -113,7 +113,7 @@ private DelegatingCodec getCodec() { } @Override - protected Map prepare(ResourceManager resourceManager, ProfilerFiller profiler) { + protected Map prepare(ResourceManager resourceManager, ProfilerFiller profiler) { var entries = super.prepare(resourceManager, profiler); getCodec().resetCodec(); diff --git a/common/src/main/java/io/wispforest/accessories/data/api/IdentifiedResourceReloadListener.java b/common/src/main/java/io/wispforest/accessories/data/api/IdentifiedResourceReloadListener.java index 33685fbcf..d8d35479c 100644 --- a/common/src/main/java/io/wispforest/accessories/data/api/IdentifiedResourceReloadListener.java +++ b/common/src/main/java/io/wispforest/accessories/data/api/IdentifiedResourceReloadListener.java @@ -1,7 +1,7 @@ package io.wispforest.accessories.data.api; import io.wispforest.accessories.AccessoriesInternals; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.server.packs.PackType; import net.minecraft.server.packs.resources.PreparableReloadListener; @@ -9,9 +9,9 @@ public interface IdentifiedResourceReloadListener extends PreparableReloadListener { - ResourceLocation getId(); + Identifier getId(); - Set getDependencyIds(); + Set getDependencyIds(); default void registerForType(PackType packType) { AccessoriesInternals.INSTANCE.registerLoader(packType, this); diff --git a/common/src/main/java/io/wispforest/accessories/data/api/LookupDataLoader.java b/common/src/main/java/io/wispforest/accessories/data/api/LookupDataLoader.java index 52b7da2f3..171a8e932 100644 --- a/common/src/main/java/io/wispforest/accessories/data/api/LookupDataLoader.java +++ b/common/src/main/java/io/wispforest/accessories/data/api/LookupDataLoader.java @@ -1,29 +1,29 @@ package io.wispforest.accessories.data.api; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.world.level.Level; import org.jetbrains.annotations.Nullable; import java.util.Map; public interface LookupDataLoader { - default Map getEntries(Level level) { + default Map getEntries(Level level) { return getEntries(level.isClientSide()); } - Map getEntries(boolean isClientSide); + Map getEntries(boolean isClientSide); @Nullable - default V getEntry(ResourceLocation id, Level level) { + default V getEntry(Identifier id, Level level) { return getEntry(id, level.isClientSide()); } @Nullable - V getEntry(ResourceLocation id, boolean isClientSide); + V getEntry(Identifier id, boolean isClientSide); - default ResourceLocation getId(V t, Level level) { + default Identifier getId(V t, Level level) { return getId(t, level.isClientSide()); } - ResourceLocation getId(V t, boolean isClientSide); + Identifier getId(V t, boolean isClientSide); } diff --git a/common/src/main/java/io/wispforest/accessories/data/api/ManagedEndecDataLoader.java b/common/src/main/java/io/wispforest/accessories/data/api/ManagedEndecDataLoader.java index fde6a99b4..1a4a523ee 100644 --- a/common/src/main/java/io/wispforest/accessories/data/api/ManagedEndecDataLoader.java +++ b/common/src/main/java/io/wispforest/accessories/data/api/ManagedEndecDataLoader.java @@ -3,7 +3,7 @@ import com.google.common.collect.BiMap; import io.wispforest.endec.Endec; import io.wispforest.endec.SerializationContext; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.server.packs.PackType; import net.minecraft.server.packs.resources.ResourceManager; import net.minecraft.util.profiling.ProfilerFiller; @@ -17,80 +17,80 @@ import java.util.function.Function; import java.util.function.IntFunction; -public abstract class ManagedEndecDataLoader extends EndecDataLoader implements SyncedDataHelper>, LookupDataLoader { +public abstract class ManagedEndecDataLoader extends EndecDataLoader implements SyncedDataHelper>, LookupDataLoader { - private final SequencedBiMap server = SequencedBiMap.of(LinkedHashMap::new); - private final SequencedBiMap client = SequencedBiMap.of(LinkedHashMap::new); + private final SequencedBiMap server = SequencedBiMap.of(LinkedHashMap::new); + private final SequencedBiMap client = SequencedBiMap.of(LinkedHashMap::new); private final Endec valueEndec; - private final Endec> mapEndec; + private final Endec> mapEndec; - protected ManagedEndecDataLoader(ResourceLocation id, String type, Endec valueEndec, Endec dataEndec, PackType packType) { + protected ManagedEndecDataLoader(Identifier id, String type, Endec valueEndec, Endec dataEndec, PackType packType) { this(id, type, valueEndec, dataEndec, packType, false); } - protected ManagedEndecDataLoader(ResourceLocation id, String type, Endec valueEndec, Endec dataEndec, PackType packType, boolean requiresRegistries) { + protected ManagedEndecDataLoader(Identifier id, String type, Endec valueEndec, Endec dataEndec, PackType packType, boolean requiresRegistries) { this(id, type, valueEndec, dataEndec, packType, SerializationContext.empty(), requiresRegistries); } - protected ManagedEndecDataLoader(ResourceLocation id, String type, Endec valueEndec, Endec dataEndec, PackType packType, Set dependencies) { + protected ManagedEndecDataLoader(Identifier id, String type, Endec valueEndec, Endec dataEndec, PackType packType, Set dependencies) { this(id, type, valueEndec, dataEndec, packType, SerializationContext.empty(), false, dependencies); } - protected ManagedEndecDataLoader(ResourceLocation id, String type, Endec valueEndec, Endec dataEndec, PackType packType, SerializationContext context, boolean requiresRegistries) { + protected ManagedEndecDataLoader(Identifier id, String type, Endec valueEndec, Endec dataEndec, PackType packType, SerializationContext context, boolean requiresRegistries) { this(id, type, valueEndec, dataEndec, packType, context, requiresRegistries, Set.of()); } - protected ManagedEndecDataLoader(ResourceLocation id, String type, Endec valueEndec, Endec dataEndec, PackType packType, SerializationContext context, boolean requiresRegistries, Set dependencies) { + protected ManagedEndecDataLoader(Identifier id, String type, Endec valueEndec, Endec dataEndec, PackType packType, SerializationContext context, boolean requiresRegistries, Set dependencies) { super(id, type, dataEndec, packType, context, requiresRegistries, dependencies); this.valueEndec = valueEndec; - this.mapEndec = biMapEndec(value -> SequencedBiMap.of(LinkedHashMap::new), ResourceLocation::toString, ResourceLocation::tryParse, valueEndec); + this.mapEndec = biMapEndec(value -> SequencedBiMap.of(LinkedHashMap::new), Identifier::toString, Identifier::tryParse, valueEndec); } - public static ManagedEndecDataLoader of(ResourceLocation id, String type, Endec valueEndec, Endec dataEndec, PackType packType, Function, Map> mapFrom) { + public static ManagedEndecDataLoader of(Identifier id, String type, Endec valueEndec, Endec dataEndec, PackType packType, Function, Map> mapFrom) { return new ManagedEndecDataLoader(id, type, valueEndec, dataEndec, packType){ @Override - public Map mapFrom(Map rawData) { + public Map mapFrom(Map rawData) { return mapFrom.apply(rawData); } }; } @Override - public Map getEntries(boolean isClientSide) { + public Map getEntries(boolean isClientSide) { return Collections.unmodifiableMap(isClientSide ? client : server); } @Override @Nullable - public V getEntry(ResourceLocation id, boolean isClientSide) { + public V getEntry(Identifier id, boolean isClientSide) { return (isClientSide ? client : server).get(id); } @Override - public ResourceLocation getId(V t, boolean isClientSide) { + public Identifier getId(V t, boolean isClientSide) { return (isClientSide ? client : server).inverse().get(t); } //-- - public abstract Map mapFrom(Map rawData); + public abstract Map mapFrom(Map rawData); protected void onSync() {} @Override - public final SequencedBiMap getServerData() { + public final SequencedBiMap getServerData() { return this.server; } @Override - public final Endec> syncDataEndec() { + public final Endec> syncDataEndec() { return this.mapEndec; } @Override - public final void onReceivedData(SequencedBiMap data) { + public final void onReceivedData(SequencedBiMap data) { this.client.clear(); this.client.putAll(data); @@ -100,7 +100,7 @@ public final void onReceivedData(SequencedBiMap data) { //-- @Override - protected void apply(Map loadedObjects, ResourceManager resourceManager, ProfilerFiller profiler) { + protected void apply(Map loadedObjects, ResourceManager resourceManager, ProfilerFiller profiler) { this.server.clear(); this.server.putAll(mapFrom(loadedObjects)); } diff --git a/common/src/main/java/io/wispforest/accessories/data/api/SimpleManagedEndecDataLoader.java b/common/src/main/java/io/wispforest/accessories/data/api/SimpleManagedEndecDataLoader.java index 3ba8d1a08..29bcab8b0 100644 --- a/common/src/main/java/io/wispforest/accessories/data/api/SimpleManagedEndecDataLoader.java +++ b/common/src/main/java/io/wispforest/accessories/data/api/SimpleManagedEndecDataLoader.java @@ -1,19 +1,19 @@ package io.wispforest.accessories.data.api; import io.wispforest.endec.Endec; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.server.packs.PackType; import java.util.Map; public class SimpleManagedEndecDataLoader extends ManagedEndecDataLoader { - protected SimpleManagedEndecDataLoader(ResourceLocation id, String type, Endec endec, PackType packType) { + protected SimpleManagedEndecDataLoader(Identifier id, String type, Endec endec, PackType packType) { super(id, type, endec, endec, packType); } @Override - public Map mapFrom(Map rawData) { + public Map mapFrom(Map rawData) { return rawData; } } diff --git a/common/src/main/java/io/wispforest/accessories/data/api/SyncedDataHelper.java b/common/src/main/java/io/wispforest/accessories/data/api/SyncedDataHelper.java index 86b30803e..ddd524cf5 100644 --- a/common/src/main/java/io/wispforest/accessories/data/api/SyncedDataHelper.java +++ b/common/src/main/java/io/wispforest/accessories/data/api/SyncedDataHelper.java @@ -1,7 +1,7 @@ package io.wispforest.accessories.data.api; import io.wispforest.endec.Endec; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; @@ -11,10 +11,10 @@ public interface SyncedDataHelper { - static SyncedDataHelper of(ResourceLocation id, Endec endec, Consumer onReceived, Supplier getDataSupplier, ResourceLocation ...dependencies){ + static SyncedDataHelper of(Identifier id, Endec endec, Consumer onReceived, Supplier getDataSupplier, Identifier ...dependencies){ return new SyncedDataHelper() { - @Override public ResourceLocation getId() { return id; } - @Override public Set getDependencyIds() { return Set.of(dependencies); } + @Override public Identifier getId() { return id; } + @Override public Set getDependencyIds() { return Set.of(dependencies); } @Override public Endec syncDataEndec() { return endec; } @@ -40,9 +40,9 @@ default Exception onReceivedDataUnsafe(Object data) { return null; } - ResourceLocation getId(); + Identifier getId(); - Set getDependencyIds(); + Set getDependencyIds(); @ApiStatus.OverrideOnly D getServerData(); diff --git a/common/src/main/java/io/wispforest/accessories/data/api/SyncedDataHelperManager.java b/common/src/main/java/io/wispforest/accessories/data/api/SyncedDataHelperManager.java index be99843d9..eb2cc33a7 100644 --- a/common/src/main/java/io/wispforest/accessories/data/api/SyncedDataHelperManager.java +++ b/common/src/main/java/io/wispforest/accessories/data/api/SyncedDataHelperManager.java @@ -7,7 +7,7 @@ import io.wispforest.owo.network.ClientAccess; import io.wispforest.owo.network.OwoNetChannel; import io.wispforest.owo.serialization.endec.MinecraftEndecs; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.world.entity.player.Player; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; @@ -21,7 +21,7 @@ public class SyncedDataHelperManager { private static final Logger LOGGER = LogUtils.getLogger(); - private static final Map> ALL_SYNCED_LOADERS = new LinkedHashMap<>(); + private static final Map> ALL_SYNCED_LOADERS = new LinkedHashMap<>(); public static void registerLoader(SyncedDataHelper loader) { if (ALL_SYNCED_LOADERS.containsKey(loader.getId())) { @@ -32,7 +32,7 @@ public static void registerLoader(SyncedDataHelper loader) { } @Nullable - public static SyncedDataHelper getLoader(ResourceLocation id) { + public static SyncedDataHelper getLoader(Identifier id) { return ALL_SYNCED_LOADERS.get(id); } @@ -45,7 +45,7 @@ public static void init(OwoNetChannel channel, Consumer> hookRe .stream() .collect(Collectors.toList()); - Set resolvedIds = new HashSet<>(); + Set resolvedIds = new HashSet<>(); for (SyncedDataHelper dataLoader : endecDataLoaders) { resolvedIds.add(dataLoader.getId()); @@ -105,7 +105,7 @@ private static void handle(SyncAllLoaderDataPacket packet, ClientAccess access) @ApiStatus.Internal private static final class SyncLoaderDataPacket { - private static final Map> CACHED_ENDECS = new HashMap<>(); + private static final Map> CACHED_ENDECS = new HashMap<>(); private static final StructEndec ENDEC = Endec.dispatched( id -> { @@ -126,10 +126,10 @@ private static final class SyncLoaderDataPacket { SyncLoaderDataPacket::id, MinecraftEndecs.IDENTIFIER); - private final ResourceLocation id; + private final Identifier id; private final Object data; - private SyncLoaderDataPacket(ResourceLocation id, Object data) { + private SyncLoaderDataPacket(Identifier id, Object data) { this.id = id; this.data = data; } @@ -146,7 +146,7 @@ private static void handle(SyncLoaderDataPacket packet, ClientAccess access) { } } - public ResourceLocation id() { + public Identifier id() { return id; } diff --git a/common/src/main/java/io/wispforest/accessories/impl/core/AccessoriesCapabilityImpl.java b/common/src/main/java/io/wispforest/accessories/impl/core/AccessoriesCapabilityImpl.java index 048403a07..0b4295f25 100644 --- a/common/src/main/java/io/wispforest/accessories/impl/core/AccessoriesCapabilityImpl.java +++ b/common/src/main/java/io/wispforest/accessories/impl/core/AccessoriesCapabilityImpl.java @@ -9,8 +9,8 @@ import io.wispforest.accessories.api.core.AccessoryRegistry; import io.wispforest.accessories.api.equip.EquipAction; import io.wispforest.accessories.api.equip.EquipCheck; -import io.wispforest.accessories.api.slot.SlotPredicateRegistry; import io.wispforest.accessories.api.slot.SlotReference; +import io.wispforest.accessories.api.slot.validator.SlotValidatorRegistry; import io.wispforest.accessories.data.EntitySlotLoader; import io.wispforest.accessories.endec.NbtMapCarrier; import io.wispforest.accessories.impl.AccessoryAttributeLogic; @@ -236,7 +236,7 @@ public Pair canEquipAccessory(ItemStack stack, boole for (var container : this.getContainers().values()) { if (container.getSize() <= 0) continue; - boolean isValid = SlotPredicateRegistry.canInsertIntoSlot(stack, container.createReference(0)); + boolean isValid = SlotValidatorRegistry.canInsertIntoSlot(stack, container.createReference(0)); // Prevents checking containers that will never allow for the given stack to be equipped within it if (!isValid || !ExtraSlotTypeProperties.getProperty(container.getSlotName(), entity.level().isClientSide()).allowEquipFromUse()) continue; @@ -251,7 +251,7 @@ public Pair canEquipAccessory(ItemStack stack, boole if (slotStack.isEmpty() && AccessoryRegistry.canUnequip(slotStack, slotReference) - && SlotPredicateRegistry.canInsertIntoSlot(stack, slotReference) + && SlotValidatorRegistry.canInsertIntoSlot(stack, slotReference) && extraCheck.isValid(slotStack, false)) { return Pair.of(container.createReference(i), (newStack) -> setStack(slotReference, newStack, false)); } @@ -269,7 +269,7 @@ public Pair canEquipAccessory(ItemStack stack, boole if (slotStack.isEmpty() || !AccessoryRegistry.canUnequip(slotStack, slotReference)) continue; - if (stack.isEmpty() || (SlotPredicateRegistry.canInsertIntoSlot(stack, slotReference) && extraCheck.isValid(slotStack, true))) { + if (stack.isEmpty() || (SlotValidatorRegistry.canInsertIntoSlot(stack, slotReference) && extraCheck.isValid(slotStack, true))) { return Pair.of(slotReference, (newStack) -> setStack(slotReference, newStack, true)); } } diff --git a/common/src/main/java/io/wispforest/accessories/impl/core/AccessoriesContainerImpl.java b/common/src/main/java/io/wispforest/accessories/impl/core/AccessoriesContainerImpl.java index a79ff6a78..e58f30627 100644 --- a/common/src/main/java/io/wispforest/accessories/impl/core/AccessoriesContainerImpl.java +++ b/common/src/main/java/io/wispforest/accessories/impl/core/AccessoriesContainerImpl.java @@ -30,9 +30,9 @@ import it.unimi.dsi.fastutil.ints.Int2BooleanLinkedOpenHashMap; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.NbtOps; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.world.Container; -import net.minecraft.world.ContainerListener; +import io.wispforest.accessories.utils.ContainerListener; import net.minecraft.world.ItemStackWithSlot; import net.minecraft.world.entity.ai.attributes.AttributeModifier; import net.minecraft.world.item.ItemStack; @@ -48,7 +48,7 @@ public class AccessoriesContainerImpl implements AccessoriesContainer, InstanceE protected AccessoriesCapability capability; private String slotName; - protected final Map modifiers = new HashMap<>(); + protected final Map modifiers = new HashMap<>(); protected final Set persistentModifiers = new HashSet<>(); protected final Set cachedModifiers = new HashSet<>(); @@ -295,7 +295,7 @@ public ExpandedContainer getCosmeticAccessories() { } @Override - public Map getModifiers() { + public Map getModifiers() { return Collections.unmodifiableMap(this.modifiers); } @@ -322,12 +322,12 @@ public void addPersistentModifier(AttributeModifier modifier) { } @Override - public boolean hasModifier(ResourceLocation location) { + public boolean hasModifier(Identifier location) { return this.modifiers.containsKey(location); } @Override - public void removeModifier(ResourceLocation location) { + public void removeModifier(Identifier location) { var modifier = this.modifiers.remove(location); if(modifier == null) return; diff --git a/common/src/main/java/io/wispforest/accessories/impl/core/AccessoriesHolderImpl.java b/common/src/main/java/io/wispforest/accessories/impl/core/AccessoriesHolderImpl.java index 4af1e3d97..661e810c7 100644 --- a/common/src/main/java/io/wispforest/accessories/impl/core/AccessoriesHolderImpl.java +++ b/common/src/main/java/io/wispforest/accessories/impl/core/AccessoriesHolderImpl.java @@ -24,7 +24,7 @@ import io.wispforest.endec.util.MapCarrierEncodable; import io.wispforest.owo.serialization.RegistriesAttribute; import io.wispforest.owo.serialization.format.nbt.NbtEndec; -import net.minecraft.Util; +import net.minecraft.util.Util; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; @@ -293,7 +293,7 @@ public void encode(MapCarrierEncodable carrier, SerializationContext ctx) { } public void read(LivingEntity entity, MapCarrier carrier, SerializationContext ctx) { - read(entity.accessoriesCapability(), entity, carrier, ctx); + read(((io.wispforest.accessories.pond.AccessoriesAPIAccess) entity).accessoriesCapability(), entity, carrier, ctx); } public void read(AccessoriesCapability capability, LivingEntity entity, MapCarrierDecodable carrier, SerializationContext ctx) { diff --git a/common/src/main/java/io/wispforest/accessories/impl/core/UnknownResponse.java b/common/src/main/java/io/wispforest/accessories/impl/core/UnknownResponse.java new file mode 100644 index 000000000..bc8a4435e --- /dev/null +++ b/common/src/main/java/io/wispforest/accessories/impl/core/UnknownResponse.java @@ -0,0 +1,16 @@ +package io.wispforest.accessories.impl.core; + +import io.wispforest.accessories.api.action.ActionResponse; +import io.wispforest.accessories.api.action.ValidationState; +import io.wispforest.accessories.api.tooltip.ListTooltipAdder; +import io.wispforest.accessories.api.tooltip.impl.ListTooltipEntry; +import net.minecraft.network.chat.Component; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.TooltipFlag; + +public record UnknownResponse(ValidationState canPerformAction) implements ActionResponse { + @Override + public void addInfo(ListTooltipAdder adder, Item.TooltipContext ctx, TooltipFlag type) { + adder.add(Component.literal(canPerformAction.isValid() ? "No Restrictions found!" : "Unknown restriction disallows such!")); + } +} diff --git a/common/src/main/java/io/wispforest/accessories/impl/event/AccessoriesEventHandler.java b/common/src/main/java/io/wispforest/accessories/impl/event/AccessoriesEventHandler.java index 0427b11b5..1d4e5a78d 100644 --- a/common/src/main/java/io/wispforest/accessories/impl/event/AccessoriesEventHandler.java +++ b/common/src/main/java/io/wispforest/accessories/impl/event/AccessoriesEventHandler.java @@ -17,6 +17,7 @@ import io.wispforest.accessories.api.data.AccessoriesTags; import io.wispforest.accessories.api.events.*; import io.wispforest.accessories.api.slot.*; +import io.wispforest.accessories.api.slot.validator.SlotValidatorRegistry; import io.wispforest.accessories.data.EntitySlotLoader; import io.wispforest.accessories.data.SlotTypeLoader; import io.wispforest.accessories.endec.NbtMapCarrier; @@ -37,6 +38,7 @@ import io.wispforest.accessories.networking.client.SyncEntireContainer; import io.wispforest.accessories.networking.client.SyncPlayerOptions; import io.wispforest.accessories.pond.AccessoriesLivingEntityExtension; +import io.wispforest.accessories.pond.TooltipFlagExtended; import io.wispforest.accessories.utils.AttributeUtils; import io.wispforest.endec.SerializationContext; import io.wispforest.owo.serialization.RegistriesAttribute; @@ -46,7 +48,7 @@ import net.minecraft.core.component.DataComponentType; import net.minecraft.network.chat.CommonComponents; import net.minecraft.network.chat.Component; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.players.PlayerList; @@ -65,7 +67,7 @@ import net.minecraft.world.item.component.TooltipDisplay; import net.minecraft.world.item.enchantment.EnchantmentEffectComponents; import net.minecraft.world.item.enchantment.EnchantmentHelper; -import net.minecraft.world.level.GameRules; +import net.minecraft.world.level.gamerules.GameRules; import net.minecraft.world.level.Level; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; @@ -146,7 +148,7 @@ private static void handleInvalidStacks(Container container, SlotReference refer if (stack.isEmpty()) return; - var bl = !SlotPredicateRegistry.canInsertIntoSlot(stack, reference); + var bl = !SlotValidatorRegistry.canInsertIntoSlot(stack, reference); if (bl) dropAndRemoveStack(container, reference, player); } @@ -274,7 +276,7 @@ public static void onLivingEntityTick(LivingEntity entity) { splitPath.removeLast(); - removedEnchantmentBuilder.addStackable(attributeHolder, new AttributeModifier(ResourceLocation.fromNamespaceAndPath(namespace, String.join("/", splitPath)), modifier.amount(), modifier.operation())); + removedEnchantmentBuilder.addStackable(attributeHolder, new AttributeModifier(Identifier.fromNamespaceAndPath(namespace, String.join("/", splitPath)), modifier.amount(), modifier.operation())); }); removedAttributesBuilder.addFrom(removedEnchantmentBuilder); @@ -293,7 +295,7 @@ public static void onLivingEntityTick(LivingEntity entity) { splitPath.removeLast(); - addedEnchantmentBuilder.addStackable(attributeHolder, new AttributeModifier(ResourceLocation.fromNamespaceAndPath(namespace, String.join("/", splitPath)), modifier.amount(), modifier.operation())); + addedEnchantmentBuilder.addStackable(attributeHolder, new AttributeModifier(Identifier.fromNamespaceAndPath(namespace, String.join("/", splitPath)), modifier.amount(), modifier.operation())); }); addedAttributesBuilder.addFrom(addedEnchantmentBuilder); @@ -473,15 +475,16 @@ private static void onStackChange(SlotReference slotReference, ItemStack lastSta AccessoryChangeCallback.EVENT.invoker().onChange(lastStack, currentStack, slotReference, stateChange); } - public static void getTooltipData(@Nullable LivingEntity entity, ItemStack stack, List tooltip,TooltipDisplay display, Item.TooltipContext tooltipContext, TooltipFlag tooltipType) { + public static void getTooltipData(@Nullable LivingEntity entity, ItemStack stack, List tooltip, TooltipDisplay display, Item.TooltipContext tooltipContext, TooltipFlag tooltipType) { var accessory = AccessoryRegistry.getAccessoryOrDefault(stack); if (accessory != null) { // Add possible client values to tooltipFlag - tooltipType = AccessoriesClientInternals.getInstance().createTooltipFlag(tooltipType); + tooltipType = ((io.wispforest.accessories.pond.TooltipFlagExtended) tooltipType).withMask(); - if (entity != null && AccessoriesCapability.get(entity) != null) + if (entity != null && AccessoriesCapability.get(entity) != null) { addEntityBasedTooltipData(entity, accessory, stack, tooltip, display, tooltipContext, tooltipType); + } accessory.getExtraTooltip(stack, tooltip, tooltipContext, tooltipType); } @@ -491,7 +494,7 @@ public static void getTooltipData(@Nullable LivingEntity entity, ItemStack stack private static void addEntityBasedTooltipData(LivingEntity entity, Accessory accessory, ItemStack stack, List tooltip, TooltipDisplay display, Item.TooltipContext tooltipContext, TooltipFlag tooltipType) { // TODO: MAYBE DEPENDING ON ENTITY OR SOMETHING SHOW ALL VALID SLOTS BUT COLOR CODE THEM IF NOT VALID FOR ENTITY? // TODO: ADD BETTER HANDLING FOR POSSIBLE SLOTS THAT ARE EQUIPABLE IN BUT IS AT ZERO SIZE - var validSlotTypes = new HashSet<>(SlotPredicateRegistry.getValidSlotTypes(entity, stack)); + var validSlotTypes = new HashSet<>(SlotValidatorRegistry.getValidSlotTypes(entity, stack)); if (validSlotTypes.isEmpty()) return; @@ -558,7 +561,7 @@ private static void addEntityBasedTooltipData(LivingEntity entity, Accessory acc } } - validSlotTypes.addAll (validUniqueSlots); + validSlotTypes.addAll(validUniqueSlots); final var filteredValidUniqueSlots = validUniqueSlots.stream() .filter(slotType -> ExtraSlotTypeProperties.getProperty(slotType.name(), true).allowTooltipInfo()) @@ -582,9 +585,9 @@ private static void addEntityBasedTooltipData(LivingEntity entity, Accessory acc var slotTranslationKey = "slot.tooltip." + ((validSlotTypes.size() > 1 && !allSlots) ? "plural" : "singular"); slotInfoComponent.append( - Component.translatable(Accessories.translationKey(slotTranslationKey)) - .withStyle(ChatFormatting.GRAY) - .append(slotsComponent.withStyle(ChatFormatting.BLUE)) + Component.translatable(Accessories.translationKey(slotTranslationKey)) + .withStyle(ChatFormatting.GRAY) + .append(slotsComponent.withStyle(ChatFormatting.BLUE)) ); tooltip.add(slotInfoComponent); @@ -719,7 +722,8 @@ public static Collection onDeath(LivingEntity entity, DamageSource so var gamerules = ((ServerLevel) entity.level()).getGameRules(); - var keepInv = gamerules.getRule(GameRules.RULE_KEEPINVENTORY).get() || gamerules.getRule(AccessoriesGameRules.RULE_KEEP_ACCESSORY_INVENTORY).get(); + var accessoriesKey = AccessoriesGameRules.getKeepAccessoryInventoryKey(); + var keepInv = gamerules.get(GameRules.KEEP_INVENTORY) || (accessoriesKey != null && gamerules.get(accessoriesKey)); for (var containerEntry : AccessoriesHolderImpl.getHolder(capability).getAllSlotContainers().entrySet()) { var slotType = containerEntry.getValue().slotType(); @@ -871,7 +875,7 @@ public static InteractionResult attemptEquipFromUse(Player player, InteractionHa public static InteractionResult attemptEquipOnEntity(Player player, InteractionHand hand, Entity entity) { var stack = player.getItemInHand(hand); - if (!(entity instanceof LivingEntity targetEntity) || !entity.getType().is(AccessoriesTags.EQUIPMENT_MANAGEABLE)) + if (!(entity instanceof LivingEntity targetEntity) || !entity.getType().builtInRegistryHolder().is(AccessoriesTags.EQUIPMENT_MANAGEABLE)) return InteractionResult.PASS; var targetCapability = AccessoriesCapability.get(targetEntity); diff --git a/common/src/main/java/io/wispforest/accessories/impl/event/AccessoryEquipmentDispenseItemBehavior.java b/common/src/main/java/io/wispforest/accessories/impl/event/AccessoryEquipmentDispenseItemBehavior.java index 9967019b2..8bdb99bc2 100644 --- a/common/src/main/java/io/wispforest/accessories/impl/event/AccessoryEquipmentDispenseItemBehavior.java +++ b/common/src/main/java/io/wispforest/accessories/impl/event/AccessoryEquipmentDispenseItemBehavior.java @@ -59,7 +59,7 @@ public static boolean canEquipWithDispenser(LivingEntity entity, ItemStack stack if (targetCapability != null) { var type = entity.getType(); - if (type.is(AccessoriesTags.MODIFIABLE_ENTITY_WHITELIST) || !type.is(AccessoriesTags.MODIFIABLE_ENTITY_BLACKLIST)) { + if (type.builtInRegistryHolder().is(AccessoriesTags.MODIFIABLE_ENTITY_WHITELIST) || !type.builtInRegistryHolder().is(AccessoriesTags.MODIFIABLE_ENTITY_BLACKLIST)) { var accessory = AccessoryRegistry.getAccessoryOrDefault(stack); var equipReference = targetCapability.canEquipAccessory(stack, false); diff --git a/common/src/main/java/io/wispforest/accessories/impl/event/VanillaItemPredicates.java b/common/src/main/java/io/wispforest/accessories/impl/event/VanillaItemPredicates.java index 26966a61b..55481bbad 100644 --- a/common/src/main/java/io/wispforest/accessories/impl/event/VanillaItemPredicates.java +++ b/common/src/main/java/io/wispforest/accessories/impl/event/VanillaItemPredicates.java @@ -1,58 +1,53 @@ package io.wispforest.accessories.impl.event; import io.wispforest.accessories.Accessories; +import io.wispforest.accessories.api.action.ActionResponse; import io.wispforest.accessories.api.data.AccessoriesBaseData; import io.wispforest.accessories.api.data.AccessoriesTags; -import io.wispforest.accessories.api.slot.SlotBasedPredicate; -import io.wispforest.accessories.api.slot.SlotPredicateRegistry; -import net.fabricmc.fabric.api.util.TriState; +import io.wispforest.accessories.api.slot.validator.SlotValidator; +import io.wispforest.accessories.api.slot.validator.SlotValidatorRegistry; import net.minecraft.core.component.DataComponents; +import net.minecraft.network.chat.Component; import net.minecraft.world.item.BannerItem; public class VanillaItemPredicates { - public static final SlotBasedPredicate ELYTRA_PREDICATE = (level, slotType, slot, stack) -> { + public static final SlotValidator ELYTRA_PREDICATE = (level, slotType, slot, stack, buffer) -> { var validSlots = Accessories.config().contentOptions.validGliderSlots(); - if (stack.has(DataComponents.GLIDER)) { - if ((validSlots.contains(slotType.name()) || validSlots.contains("any")) && Accessories.config().contentOptions.allowGliderEquip()) { - return TriState.TRUE; - } else if (slotType.name().equals("cape") && stack.is(AccessoriesTags.VALID_GLIDER_EQUIP)){ - return TriState.TRUE; - } - } + if (!stack.has(DataComponents.GLIDER)) return; - return TriState.DEFAULT; + if (Accessories.config().contentOptions.allowGliderEquip() && AccessoriesBaseData.isValidSlotWithAny(validSlots, slotType)) { + buffer.respondWith(ActionResponse.of(true, Component.literal("Found to allow the glider to be equipped as configured."))); + } else if (slotType.name().equals(AccessoriesBaseData.CAPE_SLOT) && stack.is(AccessoriesTags.VALID_GLIDER_EQUIP)){ + buffer.respondWith(ActionResponse.of(true, Component.literal("Found to allow the glider to be equipped as tagged."))); + } }; - public static final SlotBasedPredicate TOTEM_PREDICATE = (level, slotType, slot, stack) -> { + public static final SlotValidator TOTEM_PREDICATE = (level, slotType, slot, stack, buffer) -> { var validSlots = Accessories.config().contentOptions.validTotemSlots(); - if(stack.has(DataComponents.DEATH_PROTECTION)) { - if ((validSlots.contains(slotType.name()) || validSlots.contains("any")) && Accessories.config().contentOptions.allowTotemEquip()) { - return TriState.TRUE; - } else if (slotType.name().equals(AccessoriesBaseData.CHARM_SLOT) && stack.is(AccessoriesTags.VALID_TOTEM_EQUIP)){ - return TriState.TRUE; - } - } + if(stack.has(DataComponents.DEATH_PROTECTION)) return; - return TriState.DEFAULT; + if (Accessories.config().contentOptions.allowTotemEquip() && AccessoriesBaseData.isValidSlotWithAny(validSlots, slotType)) { + buffer.respondWith(ActionResponse.of(true, Component.literal("Found to allow the totem to be equipped as configured."))); + } else if (slotType.name().equals(AccessoriesBaseData.CHARM_SLOT) && stack.is(AccessoriesTags.VALID_TOTEM_EQUIP)){ + buffer.respondWith(ActionResponse.of(true, Component.literal("Found to allow the totem to be equipped as tagged."))); + } }; - public static final SlotBasedPredicate BANNER_PREDICATE = (level, slotType, slot, stack) -> { + public static final SlotValidator BANNER_PREDICATE = (level, slotType, slot, stack, buffer) -> { var validSlots = Accessories.config().contentOptions.validBannerSlots(); - if(stack.getItem() instanceof BannerItem) { - if ((validSlots.contains(slotType.name()) || validSlots.contains("any")) && Accessories.config().contentOptions.allowBannerEquip()) { - return TriState.TRUE; - } - } + if(!(stack.getItem() instanceof BannerItem)) return; - return TriState.DEFAULT; + if (Accessories.config().contentOptions.allowBannerEquip() && AccessoriesBaseData.isValidSlotWithAny(validSlots, slotType)) { + buffer.respondWith(ActionResponse.of(true, Component.literal("Found to allow the banner to be equipped as configured."))); + } }; public static void init() { - SlotPredicateRegistry.register(Accessories.of("elytra_item"), ELYTRA_PREDICATE); - SlotPredicateRegistry.register(Accessories.of("totem_item"), TOTEM_PREDICATE); - SlotPredicateRegistry.register(Accessories.of("banner_item"), BANNER_PREDICATE); + SlotValidatorRegistry.register(Accessories.of("elytra_item"), ELYTRA_PREDICATE); + SlotValidatorRegistry.register(Accessories.of("totem_item"), TOTEM_PREDICATE); + SlotValidatorRegistry.register(Accessories.of("banner_item"), BANNER_PREDICATE); } } diff --git a/common/src/main/java/io/wispforest/accessories/impl/event/WrappedEvent.java b/common/src/main/java/io/wispforest/accessories/impl/event/WrappedEvent.java index 7161852d8..a4225c820 100644 --- a/common/src/main/java/io/wispforest/accessories/impl/event/WrappedEvent.java +++ b/common/src/main/java/io/wispforest/accessories/impl/event/WrappedEvent.java @@ -1,7 +1,7 @@ package io.wispforest.accessories.impl.event; import net.fabricmc.fabric.api.event.Event; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import java.util.function.Function; @@ -31,14 +31,14 @@ public void register(T listener) { } @Override - public void register(ResourceLocation phase, T listener) { + public void register(Identifier phase, T listener) { var wrappedListener = this.conversionFunc.apply(listener); this.targetEvent.register(phase, wrappedListener); } @Override - public void addPhaseOrdering(ResourceLocation firstPhase, ResourceLocation secondPhase) { + public void addPhaseOrdering(Identifier firstPhase, Identifier secondPhase) { this.targetEvent.addPhaseOrdering(firstPhase, secondPhase); } } diff --git a/common/src/main/java/io/wispforest/accessories/impl/slot/SlotGroupImpl.java b/common/src/main/java/io/wispforest/accessories/impl/slot/SlotGroupImpl.java index 9df97172b..71a0a797a 100644 --- a/common/src/main/java/io/wispforest/accessories/impl/slot/SlotGroupImpl.java +++ b/common/src/main/java/io/wispforest/accessories/impl/slot/SlotGroupImpl.java @@ -5,13 +5,13 @@ import io.wispforest.endec.StructEndec; import io.wispforest.endec.impl.StructEndecBuilder; import io.wispforest.owo.serialization.endec.MinecraftEndecs; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.Set; -public record SlotGroupImpl(String name, int order, Set slots, ResourceLocation icon) implements SlotGroup { +public record SlotGroupImpl(String name, int order, Set slots, Identifier icon) implements SlotGroup { public static final StructEndec ENDEC = StructEndecBuilder.of( Endec.STRING.fieldOf("name", SlotGroup::name), diff --git a/common/src/main/java/io/wispforest/accessories/impl/slot/SlotTypeImpl.java b/common/src/main/java/io/wispforest/accessories/impl/slot/SlotTypeImpl.java index 27d6e569d..1064c2283 100644 --- a/common/src/main/java/io/wispforest/accessories/impl/slot/SlotTypeImpl.java +++ b/common/src/main/java/io/wispforest/accessories/impl/slot/SlotTypeImpl.java @@ -7,13 +7,13 @@ import io.wispforest.endec.StructEndec; import io.wispforest.endec.impl.StructEndecBuilder; import io.wispforest.owo.serialization.endec.MinecraftEndecs; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import java.util.Optional; import java.util.Set; -public record SlotTypeImpl(String name, Optional alternativeTranslation, ResourceLocation icon, int order, int amount, Set validators, DropRule dropRule) implements SlotType { - public SlotTypeImpl(String name, ResourceLocation icon, int order, int amount, Set validators, DropRule dropRule) { +public record SlotTypeImpl(String name, Optional alternativeTranslation, Identifier icon, int order, int amount, Set validators, DropRule dropRule) implements SlotType { + public SlotTypeImpl(String name, Identifier icon, int order, int amount, Set validators, DropRule dropRule) { this(name, Optional.empty(), icon, order, amount, validators, dropRule); } diff --git a/common/src/main/java/io/wispforest/accessories/menu/AccessoriesArmorSlot.java b/common/src/main/java/io/wispforest/accessories/menu/AccessoriesArmorSlot.java index 5af4a81f4..96588be22 100644 --- a/common/src/main/java/io/wispforest/accessories/menu/AccessoriesArmorSlot.java +++ b/common/src/main/java/io/wispforest/accessories/menu/AccessoriesArmorSlot.java @@ -1,7 +1,7 @@ package io.wispforest.accessories.menu; import io.wispforest.accessories.api.AccessoriesContainer; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.world.Container; import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.LivingEntity; @@ -12,7 +12,7 @@ public class AccessoriesArmorSlot extends ArmorSlot implements SlotTypeAccessibl public final AccessoriesContainer accessoriesContainer; - public AccessoriesArmorSlot(AccessoriesContainer accessoriesContainer, Container container, LivingEntity livingEntity, EquipmentSlot equipmentSlot, int slot, int x, int y, @Nullable ResourceLocation resourceLocation) { + public AccessoriesArmorSlot(AccessoriesContainer accessoriesContainer, Container container, LivingEntity livingEntity, EquipmentSlot equipmentSlot, int slot, int x, int y, @Nullable Identifier resourceLocation) { super(container, livingEntity, equipmentSlot, slot, x, y, resourceLocation); this.accessoriesContainer = accessoriesContainer; @@ -27,4 +27,9 @@ public AccessoriesContainer getContainer() { public int index() { return this.index; } + + @Override + public boolean isCosmeticSlot() { + return false; + } } diff --git a/common/src/main/java/io/wispforest/accessories/menu/ArmorSlotTypes.java b/common/src/main/java/io/wispforest/accessories/menu/ArmorSlotTypes.java index 02c077366..92364cbe6 100644 --- a/common/src/main/java/io/wispforest/accessories/menu/ArmorSlotTypes.java +++ b/common/src/main/java/io/wispforest/accessories/menu/ArmorSlotTypes.java @@ -1,19 +1,21 @@ package io.wispforest.accessories.menu; import io.wispforest.accessories.Accessories; +import io.wispforest.accessories.api.action.ActionResponse; +import io.wispforest.accessories.api.action.ActionResponseBuffer; import io.wispforest.accessories.api.core.Accessory; -import io.wispforest.accessories.api.slot.EntityBasedPredicate; -import io.wispforest.accessories.api.slot.SlotPredicateRegistry; import io.wispforest.accessories.api.slot.SlotTypeReference; import io.wispforest.accessories.api.slot.UniqueSlotHandling; +import io.wispforest.accessories.api.slot.validator.EntitySlotValidator; +import io.wispforest.accessories.api.slot.validator.SlotValidatorRegistry; import io.wispforest.accessories.impl.slot.StrictMode; -import net.fabricmc.fabric.api.util.TriState; import net.minecraft.core.component.DataComponents; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.Identifier; import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.animal.horse.AbstractHorse; -import net.minecraft.world.entity.animal.horse.Llama; +import net.minecraft.world.entity.animal.equine.AbstractHorse; +import net.minecraft.world.entity.animal.equine.Llama; import net.minecraft.world.inventory.InventoryMenu; import net.minecraft.world.item.ItemStack; import org.jetbrains.annotations.Nullable; @@ -23,14 +25,14 @@ public class ArmorSlotTypes implements UniqueSlotHandling.RegistrationCallback { - private static final ResourceLocation SADDLE_SLOT_SPRITE = ResourceLocation.withDefaultNamespace("container/slot/saddle"); + private static final Identifier SADDLE_SLOT_SPRITE = Identifier.withDefaultNamespace("container/slot/saddle"); - private static final ResourceLocation LLAMA_ARMOR_SLOT_SPRITE = ResourceLocation.withDefaultNamespace("container/slot/llama_armor"); - private static final ResourceLocation HORSE_ARMOR_SLOT_SPRITE = ResourceLocation.withDefaultNamespace("container/slot/horse_armor"); + private static final Identifier LLAMA_ARMOR_SLOT_SPRITE = Identifier.withDefaultNamespace("container/slot/llama_armor"); + private static final Identifier HORSE_ARMOR_SLOT_SPRITE = Identifier.withDefaultNamespace("container/slot/horse_armor"); private static final Accessory armorAccessory = new Accessory() {}; - public static final Map TEXTURE_EMPTY_SLOTS = Map.of( + public static final Map TEXTURE_EMPTY_SLOTS = Map.of( EquipmentSlot.FEET, InventoryMenu.EMPTY_ARMOR_SLOT_BOOTS, EquipmentSlot.LEGS, InventoryMenu.EMPTY_ARMOR_SLOT_LEGGINGS, EquipmentSlot.CHEST, InventoryMenu.EMPTY_ARMOR_SLOT_CHESTPLATE, @@ -42,15 +44,15 @@ public class ArmorSlotTypes implements UniqueSlotHandling.RegistrationCallback { public static final ArmorSlotTypes INSTANCE = new ArmorSlotTypes(); - private static final ResourceLocation HEAD_PREDICATE_LOCATION = of("head"); - private static final ResourceLocation CHEST_PREDICATE_LOCATION = of("chest"); - private static final ResourceLocation LEGS_PREDICATE_LOCATION = of("legs"); - private static final ResourceLocation FEET_PREDICATE_LOCATION = of("feet"); - private static final ResourceLocation ANIMAL_BODY_PREDICATE_LOCATION = of("animal_body"); - private static final ResourceLocation SADDLE_PREDICATE_LOCATION = of("saddle"); + private static final Identifier HEAD_PREDICATE_LOCATION = of("head"); + private static final Identifier CHEST_PREDICATE_LOCATION = of("chest"); + private static final Identifier LEGS_PREDICATE_LOCATION = of("legs"); + private static final Identifier FEET_PREDICATE_LOCATION = of("feet"); + private static final Identifier ANIMAL_BODY_PREDICATE_LOCATION = of("animal_body"); + private static final Identifier SADDLE_PREDICATE_LOCATION = of("saddle"); - public static ResourceLocation of(String path) { - return ResourceLocation.fromNamespaceAndPath(Accessories.MODID + "_" + "cosmetics", path); + public static Identifier of(String path) { + return Identifier.fromNamespaceAndPath(Accessories.MODID + "_" + "cosmetics", path); } private SlotTypeReference headSlotReference = null; @@ -98,7 +100,7 @@ public static List getArmorReferences() { } @Nullable - public static ResourceLocation getEmptyTexture(EquipmentSlot slot, LivingEntity living) { + public static Identifier getEmptyTexture(EquipmentSlot slot, LivingEntity living) { var texture = TEXTURE_EMPTY_SLOTS.get(slot); if (texture != null) return texture; @@ -135,12 +137,12 @@ public static boolean isValidEquipable(EquipmentSlot equipmentSlot) { public void init() { UniqueSlotHandling.EVENT.register(this); - SlotPredicateRegistry.register(HEAD_PREDICATE_LOCATION, (EntityBasedPredicate) ((level, entity, slotType, slot, stack) -> isValid(entity, stack, EquipmentSlot.HEAD))); - SlotPredicateRegistry.register(CHEST_PREDICATE_LOCATION, (EntityBasedPredicate) ((level, entity, slotType, slot, stack) -> isValid(entity, stack, EquipmentSlot.CHEST))); - SlotPredicateRegistry.register(LEGS_PREDICATE_LOCATION, (EntityBasedPredicate) ((level, entity, slotType, slot, stack) -> isValid(entity, stack, EquipmentSlot.LEGS))); - SlotPredicateRegistry.register(FEET_PREDICATE_LOCATION, (EntityBasedPredicate) ((level, entity, slotType, slot, stack) -> isValid(entity, stack, EquipmentSlot.FEET))); - SlotPredicateRegistry.register(ANIMAL_BODY_PREDICATE_LOCATION, (EntityBasedPredicate) ((level, entity, slotType, slot, stack) -> isValid(entity, stack, EquipmentSlot.BODY))); - SlotPredicateRegistry.register(SADDLE_PREDICATE_LOCATION, (EntityBasedPredicate) ((level, entity, slotType, slot, stack) -> isValid(entity, stack, EquipmentSlot.SADDLE))); + SlotValidatorRegistry.register(HEAD_PREDICATE_LOCATION, (EntitySlotValidator) ((entity, level, slotType, slot, stack, buffer) -> isValid(entity, stack, EquipmentSlot.HEAD, buffer))); + SlotValidatorRegistry.register(CHEST_PREDICATE_LOCATION, (EntitySlotValidator) ((entity, level, slotType, slot, stack, buffer) -> isValid(entity, stack, EquipmentSlot.CHEST, buffer))); + SlotValidatorRegistry.register(LEGS_PREDICATE_LOCATION, (EntitySlotValidator) ((entity, level, slotType, slot, stack, buffer) -> isValid(entity, stack, EquipmentSlot.LEGS, buffer))); + SlotValidatorRegistry.register(FEET_PREDICATE_LOCATION, (EntitySlotValidator) ((entity, level, slotType, slot, stack, buffer) -> isValid(entity, stack, EquipmentSlot.FEET, buffer))); + SlotValidatorRegistry.register(ANIMAL_BODY_PREDICATE_LOCATION, (EntitySlotValidator) ((entity, level, slotType, slot, stack, buffer) -> isValid(entity, stack, EquipmentSlot.BODY, buffer))); + SlotValidatorRegistry.register(SADDLE_PREDICATE_LOCATION, (EntitySlotValidator) ((entity, level, slotType, slot, stack, buffer) -> isValid(entity, stack, EquipmentSlot.SADDLE, buffer))); } @Override @@ -194,7 +196,7 @@ public void registerSlots(UniqueSlotHandling.UniqueSlotBuilderFactory factory) { .build(); } - private static TriState isValid(@Nullable LivingEntity livingEntity, ItemStack stack, EquipmentSlot equipmentSlot) { + private static void isValid(@Nullable LivingEntity livingEntity, ItemStack stack, EquipmentSlot equipmentSlot, ActionResponseBuffer buffer) { EquipmentSlot stackEquipmentSlot = null; if(livingEntity == null) { @@ -205,12 +207,14 @@ private static TriState isValid(@Nullable LivingEntity livingEntity, ItemStack s stackEquipmentSlot = livingEntity.getEquipmentSlotForItem(stack); } - return equipmentSlot.equals(stackEquipmentSlot) ? TriState.TRUE : TriState.DEFAULT; + if (equipmentSlot.equals(stackEquipmentSlot)) { + buffer.respondWith(ActionResponse.of(true, Component.literal("Given stack fits within '" + equipmentSlot.getName() + "' slot."))); + } } @Nullable public static ItemStack getAlternativeStack(LivingEntity instance, EquipmentSlot equipmentSlot) { - var capability = instance.accessoriesCapability(); + var capability = ((io.wispforest.accessories.pond.AccessoriesAPIAccess) instance).accessoriesCapability(); if (capability != null) { var reference = ArmorSlotTypes.getReferenceFromSlot(equipmentSlot); diff --git a/common/src/main/java/io/wispforest/accessories/menu/SlotAccessContainer.java b/common/src/main/java/io/wispforest/accessories/menu/SlotAccessContainer.java index a7355000c..946e4cf9f 100644 --- a/common/src/main/java/io/wispforest/accessories/menu/SlotAccessContainer.java +++ b/common/src/main/java/io/wispforest/accessories/menu/SlotAccessContainer.java @@ -25,7 +25,18 @@ public static Container ofArmor(EquipmentSlot equipmentSlot, LivingEntity living } public static Container ofGenericArmor(EquipmentSlot equipmentSlot, LivingEntity livingEntity) { - return new SlotAccessContainer(SlotAccess.forEquipmentSlot(livingEntity, equipmentSlot)); + return new SlotAccessContainer(new SlotAccess() { + @Override + public ItemStack get() { + return livingEntity.getItemBySlot(equipmentSlot); + } + + @Override + public boolean set(ItemStack stack) { + livingEntity.setItemSlot(equipmentSlot, stack); + return true; + } + }); } @Nullable @@ -40,7 +51,19 @@ public static Container ofPlayerArmor(EquipmentSlot equipmentSlot, Player player if(index == 40) return null; - return new SlotAccessContainer(SlotAccess.forContainer(player.getInventory(), index)); + final int containerIndex = index; + return new SlotAccessContainer(new SlotAccess() { + @Override + public ItemStack get() { + return player.getInventory().getItem(containerIndex); + } + + @Override + public boolean set(ItemStack stack) { + player.getInventory().setItem(containerIndex, stack); + return true; + } + }); } //-- diff --git a/common/src/main/java/io/wispforest/accessories/menu/SlotTypeAccessible.java b/common/src/main/java/io/wispforest/accessories/menu/SlotTypeAccessible.java index 8d03cc878..93ae0b238 100644 --- a/common/src/main/java/io/wispforest/accessories/menu/SlotTypeAccessible.java +++ b/common/src/main/java/io/wispforest/accessories/menu/SlotTypeAccessible.java @@ -2,6 +2,7 @@ import io.wispforest.accessories.api.AccessoriesContainer; import io.wispforest.accessories.api.slot.SlotPath; +import io.wispforest.accessories.api.slot.SlotReference; import io.wispforest.accessories.api.slot.SlotType; public interface SlotTypeAccessible { @@ -10,6 +11,8 @@ public interface SlotTypeAccessible { int index(); + boolean isCosmeticSlot(); + default String slotName() { return getContainer().getSlotName(); } @@ -22,7 +25,7 @@ default SlotPath slotPath() { return getContainer().createPath(index()); } - default boolean isCosmeticSlot() { - return false; + default SlotReference slotReference() { + return getContainer().createReference(index()); } } diff --git a/common/src/main/java/io/wispforest/accessories/menu/variants/AccessoriesMenu.java b/common/src/main/java/io/wispforest/accessories/menu/variants/AccessoriesMenu.java index 6c9c3c18e..9765a1db8 100644 --- a/common/src/main/java/io/wispforest/accessories/menu/variants/AccessoriesMenu.java +++ b/common/src/main/java/io/wispforest/accessories/menu/variants/AccessoriesMenu.java @@ -4,6 +4,7 @@ import io.wispforest.accessories.api.AccessoriesContainer; import io.wispforest.accessories.api.menu.AccessoriesBasedSlot; import io.wispforest.accessories.api.slot.*; +import io.wispforest.accessories.api.slot.validator.SlotValidatorRegistry; import io.wispforest.accessories.data.SlotGroupLoader; import io.wispforest.accessories.impl.core.ExpandedContainer; import io.wispforest.accessories.impl.option.AccessoriesPlayerOptionsHolder; @@ -12,7 +13,7 @@ import io.wispforest.accessories.menu.networking.ToggledSlots; import io.wispforest.owo.client.screens.SlotGenerator; import it.unimi.dsi.fastutil.Pair; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.world.Container; import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.LivingEntity; @@ -82,7 +83,7 @@ public void setByPlayer(ItemStack itemStack, ItemStack itemStack2) { } @Override - public ResourceLocation getNoItemIcon() { + public Identifier getNoItemIcon() { return InventoryMenu.EMPTY_ARMOR_SLOT_SHIELD; } }); @@ -126,12 +127,14 @@ public ResourceLocation getNoItemIcon() { if (container == null || container.slotType() == null) continue; for (int i = 0; i < container.getSize(); i++) { - var cosmeticSlot = new AccessoriesBasedSlot(container, container.getCosmeticAccessories(), i, -300, -300); + var cosmeticSlot = new AccessoriesBasedSlot(container, container.getCosmeticAccessories(), i, -300, -300) + .ownerPlayer(this::owner); this.addSlot(cosmeticSlot); this.accessoriesSpecificSlots.add(cosmeticSlot); - var baseSlot = new AccessoriesBasedSlot(container, container.getAccessories(), i, -300, -300); + var baseSlot = new AccessoriesBasedSlot(container, container.getAccessories(), i, -300, -300) + .ownerPlayer(this::owner); this.addSlot(baseSlot); this.accessoriesSpecificSlots.add(baseSlot); @@ -161,7 +164,7 @@ public void setTheItem(ItemStack item) { @Override public boolean stillValid(Player player) { - return player.getVehicle() == living || player.canInteractWithEntity(living, 4.0); + return player.getVehicle() == living || player.distanceTo(living) <= player.entityInteractionRange() + 4.0; } @Override public void setChanged() {} @@ -181,10 +184,10 @@ private boolean addArmorSlot(EquipmentSlot equipmentSlot, LivingEntity targetEnt var cosmeticSlot = new AccessoriesBasedSlot(container, container.getCosmeticAccessories(), 0, -300, -300){ @Override - public @Nullable ResourceLocation getNoItemIcon() { + public @Nullable Identifier getNoItemIcon() { return location; } - }; + }.ownerPlayer(this::owner); this.addSlot(cosmeticSlot); @@ -258,7 +261,7 @@ public void updateUsedSlots() { var currentlyUsedSlots = AccessoriesCapability.getUsedSlotsFor(entity, this.owner.getInventory()); - currentlyUsedSlots.addAll(SlotPredicateRegistry.getValidSlotTypes(entity, this.getCarried())); + currentlyUsedSlots.addAll(SlotValidatorRegistry.getValidSlotTypes(entity, this.getCarried())); if(!currentlyUsedSlots.isEmpty()) { this.usedSlots.addAll(currentlyUsedSlots); @@ -278,7 +281,7 @@ private static Set usedGroups(LivingEntity targetEntity, Set { if (UniqueSlotHandling.isUniqueSlot(slotType.name())) return false; - var capability = targetEntity.accessoriesCapability(); + var capability = ((io.wispforest.accessories.pond.AccessoriesAPIAccess) targetEntity).accessoriesCapability(); if (capability == null) return false; @@ -431,11 +434,11 @@ public boolean stillValid(Player player) { } protected boolean canMoveToAccessorySlot(ItemStack stack, LivingEntity living) { - var capability = living.accessoriesCapability(); + var capability = ((io.wispforest.accessories.pond.AccessoriesAPIAccess) living).accessoriesCapability(); if (capability == null) return false; - var validSlotTypes = SlotPredicateRegistry.getStackSlotTypes(living, stack); + var validSlotTypes = SlotValidatorRegistry.getStackSlotTypes(living, stack); for (var slot : this.slots.subList(this.startingAccessoriesSlot, this.slots.size())) { if (slot instanceof SlotTypeAccessible accessible && validSlotTypes.contains(accessible.slotType())) return true; diff --git a/common/src/main/java/io/wispforest/accessories/misc/AccessoriesGameRules.java b/common/src/main/java/io/wispforest/accessories/misc/AccessoriesGameRules.java index e8b24d38d..be26668b6 100644 --- a/common/src/main/java/io/wispforest/accessories/misc/AccessoriesGameRules.java +++ b/common/src/main/java/io/wispforest/accessories/misc/AccessoriesGameRules.java @@ -1,27 +1,21 @@ package io.wispforest.accessories.misc; -import io.wispforest.accessories.mixin.GameRulesAccessor; -import net.minecraft.world.level.GameRules; +import net.minecraft.world.level.gamerules.GameRule; import org.jetbrains.annotations.ApiStatus; - -import java.util.function.Consumer; - -import static net.minecraft.world.level.GameRules.*; +import org.jetbrains.annotations.Nullable; @ApiStatus.Internal public class AccessoriesGameRules { - public static final GameRules.Key RULE_KEEP_ACCESSORY_INVENTORY = register("keepAccessoryInventory", Category.PLAYER, createBooleanRuleType(false)); - - public static > Key register(String name, Category category, Type type) { - return GameRulesAccessor.accessories$register("accessories." + name, category, type); - } + @Nullable + private static GameRule RULE_KEEP_ACCESSORY_INVENTORY = null; - public static GameRules.Type createBooleanRuleType(boolean defaultValue) { - return createBooleanRuleType(defaultValue, (booleanValue) -> {}); + public static void init(GameRule key) { + RULE_KEEP_ACCESSORY_INVENTORY = key; } - public static GameRules.Type createBooleanRuleType(boolean defaultValue, Consumer consumer) { - return GameRulesAccessor.BooleanValueAccessor.accessories$create(defaultValue, (server, booleanValue) -> consumer.accept(booleanValue)); + @Nullable + public static GameRule getKeepAccessoryInventoryKey() { + return RULE_KEEP_ACCESSORY_INVENTORY; } } diff --git a/common/src/main/java/io/wispforest/accessories/mixin/DataPackContentsMixin.java b/common/src/main/java/io/wispforest/accessories/mixin/DataPackContentsMixin.java index b180a7575..d48cace94 100644 --- a/common/src/main/java/io/wispforest/accessories/mixin/DataPackContentsMixin.java +++ b/common/src/main/java/io/wispforest/accessories/mixin/DataPackContentsMixin.java @@ -10,7 +10,7 @@ // Copied 1:1 from https://github.com/FabricMC/fabric/blob/625ef353552d973b6ed26c720dfa892e064afeef/fabric-resource-conditions-api-v1/src/main/java/net/fabricmc/fabric/mixin/resource/conditions/DataPackContentsMixin.java#L41 @Mixin(ReloadableServerResources.class) public abstract class DataPackContentsMixin { - @Inject(method = "updateStaticRegistryTags", at = @At("TAIL")) + @Inject(method = "updateComponentsAndStaticRegistryTags", at = @At("TAIL")) private void removeLoadedTags(CallbackInfo ci) { EntitySlotLoader.INSTANCE.buildEntryMap(); } diff --git a/common/src/main/java/io/wispforest/accessories/mixin/EnchantCommandAccessor.java b/common/src/main/java/io/wispforest/accessories/mixin/EnchantCommandAccessor.java new file mode 100644 index 000000000..c9c614d3d --- /dev/null +++ b/common/src/main/java/io/wispforest/accessories/mixin/EnchantCommandAccessor.java @@ -0,0 +1,15 @@ +package io.wispforest.accessories.mixin; + +import com.mojang.brigadier.exceptions.Dynamic2CommandExceptionType; +import com.mojang.brigadier.exceptions.DynamicCommandExceptionType; +import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; +import org.spongepowered.asm.mixin.gen.Accessor; + +@org.spongepowered.asm.mixin.Mixin(net.minecraft.server.commands.EnchantCommand.class) +public interface EnchantCommandAccessor { + @Accessor("ERROR_NOT_LIVING_ENTITY") static DynamicCommandExceptionType accessories$ERROR_NOT_LIVING_ENTITY() { throw new UnsupportedOperationException(); } + @Accessor("ERROR_NO_ITEM") static DynamicCommandExceptionType accessories$ERROR_NO_ITEM() { throw new UnsupportedOperationException(); } + @Accessor("ERROR_INCOMPATIBLE") static DynamicCommandExceptionType accessories$ERROR_INCOMPATIBLE() { throw new UnsupportedOperationException(); } + @Accessor("ERROR_LEVEL_TOO_HIGH") static Dynamic2CommandExceptionType accessories$ERROR_LEVEL_TOO_HIGH() { throw new UnsupportedOperationException(); } + @Accessor("ERROR_NOTHING_HAPPENED") static SimpleCommandExceptionType accessories$ERROR_NOTHING_HAPPENED() { throw new UnsupportedOperationException(); } +} diff --git a/common/src/main/java/io/wispforest/accessories/mixin/EnchantmentHelperMixin.java b/common/src/main/java/io/wispforest/accessories/mixin/EnchantmentHelperMixin.java index 3f25d3fdc..738850a27 100644 --- a/common/src/main/java/io/wispforest/accessories/mixin/EnchantmentHelperMixin.java +++ b/common/src/main/java/io/wispforest/accessories/mixin/EnchantmentHelperMixin.java @@ -50,7 +50,7 @@ private static Collection addAccessoriesStacks(Map instance, Operatio var returnValue = new ArrayList<>(original.call(instance)); //if(Accessories.enchantmentValidForRedirect(enchantment)) { - var capability = entity.accessoriesCapability(); + var capability = ((io.wispforest.accessories.pond.AccessoriesAPIAccess) entity).accessoriesCapability(); if(capability != null) { returnValue.addAll(capability.getAllEquipped().stream().map(SlotEntryReference::stack).toList()); @@ -73,7 +73,7 @@ private static Collection addAccessoriesStacks(Map instance, Operatio @Inject(method = "getRandomItemWith", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;getRandom()Lnet/minecraft/util/RandomSource;")) private static void adjustListForAccessories(DataComponentType dataComponentType, LivingEntity livingEntity, Predicate predicate, CallbackInfoReturnable> cir, @Local(ordinal = 0) List list) { - var capability = livingEntity.accessoriesCapability(); + var capability = ((io.wispforest.accessories.pond.AccessoriesAPIAccess) livingEntity).accessoriesCapability(); if(capability != null){ var allEquippedAccessories = capability @@ -109,7 +109,7 @@ private static void adjustListForAccessories(DataComponentType dataComponentT @Inject(method = "runIterationOnEquipment", at = @At("TAIL")) private static void adjustIterationWithAccessories(LivingEntity livingEntity, EnchantmentHelper.EnchantmentInSlotVisitor enchantmentInSlotVisitor, CallbackInfo ci) { - var capability = livingEntity.accessoriesCapability(); + var capability = ((io.wispforest.accessories.pond.AccessoriesAPIAccess) livingEntity).accessoriesCapability(); if(capability != null){ capability.getAllEquipped() @@ -168,17 +168,6 @@ record = new EnchantedItemInUse(itemStack, inSlot, owner, item -> ref.breakStack return record; } - @WrapOperation(method = "method_60148", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/enchantment/Enchantment;matchingSlot(Lnet/minecraft/world/entity/EquipmentSlot;)Z")) - private static boolean allowAccessoriesSlotEnchentments(Enchantment instance, EquipmentSlot slot, Operation original) { - if (slot.equals(AccessoriesInternals.INSTANCE.getInternalEquipmentSlot())) { - var valid = enchantmentValidForRedirect(null, instance); - - if(valid != null) return valid; - } - - return original.call(instance, slot); - } - @Unique @Nullable private static Boolean enchantmentValidForRedirect(@Nullable RegistryAccess access, Enchantment enchantment) { diff --git a/common/src/main/java/io/wispforest/accessories/mixin/FileToIdConverterMixin.java b/common/src/main/java/io/wispforest/accessories/mixin/FileToIdConverterMixin.java index f8b98ddd8..694a06c2a 100644 --- a/common/src/main/java/io/wispforest/accessories/mixin/FileToIdConverterMixin.java +++ b/common/src/main/java/io/wispforest/accessories/mixin/FileToIdConverterMixin.java @@ -2,7 +2,7 @@ import io.wispforest.accessories.pond.ContextedFileToIdConverter; import net.minecraft.resources.FileToIdConverter; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -13,17 +13,17 @@ public abstract class FileToIdConverterMixin implements ContextedFileToIdConverter { @Unique - private final Map contextData = new HashMap<>(); + private final Map contextData = new HashMap<>(); @Override - public FileToIdConverter setData(ResourceLocation location, T t) { + public FileToIdConverter setData(Identifier location, T t) { contextData.put(location, t); return (FileToIdConverter) (Object) this; } @Override - public T getData(ResourceLocation location) { + public T getData(Identifier location) { return (T) contextData.get(location); } } diff --git a/common/src/main/java/io/wispforest/accessories/mixin/GameRulesAccessor.java b/common/src/main/java/io/wispforest/accessories/mixin/GameRulesAccessor.java deleted file mode 100644 index f6bd86219..000000000 --- a/common/src/main/java/io/wispforest/accessories/mixin/GameRulesAccessor.java +++ /dev/null @@ -1,24 +0,0 @@ -package io.wispforest.accessories.mixin; - -import net.minecraft.server.MinecraftServer; -import net.minecraft.world.level.GameRules; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Invoker; - -import java.util.function.BiConsumer; - -@Mixin(GameRules.class) -public interface GameRulesAccessor { - @Invoker("register") - static > GameRules.Key accessories$register(String name, GameRules.Category category, GameRules.Type type) { - throw new IllegalStateException("UHHHHHHHHH"); - } - - @Mixin(GameRules.BooleanValue.class) - interface BooleanValueAccessor { - @Invoker("create") - static GameRules.Type accessories$create(boolean defaultValue, BiConsumer changeListener) { - throw new IllegalStateException("UHHHHHHHHH"); - } - } -} diff --git a/common/src/main/java/io/wispforest/accessories/mixin/HorseInventoryMenuAccessor.java b/common/src/main/java/io/wispforest/accessories/mixin/HorseInventoryMenuAccessor.java index 07bdffaf6..535479cbc 100644 --- a/common/src/main/java/io/wispforest/accessories/mixin/HorseInventoryMenuAccessor.java +++ b/common/src/main/java/io/wispforest/accessories/mixin/HorseInventoryMenuAccessor.java @@ -1,12 +1,12 @@ package io.wispforest.accessories.mixin; -import net.minecraft.world.entity.animal.horse.AbstractHorse; -import net.minecraft.world.inventory.HorseInventoryMenu; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.inventory.AbstractMountInventoryMenu; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; -@Mixin(HorseInventoryMenu.class) +@Mixin(AbstractMountInventoryMenu.class) public interface HorseInventoryMenuAccessor { - @Accessor("horse") - AbstractHorse accessories$horse(); + @Accessor("mount") + LivingEntity accessories$horse(); } diff --git a/common/src/main/java/io/wispforest/accessories/mixin/LivingEntityMixin.java b/common/src/main/java/io/wispforest/accessories/mixin/LivingEntityMixin.java index 46caf09d4..b64aeb7fa 100644 --- a/common/src/main/java/io/wispforest/accessories/mixin/LivingEntityMixin.java +++ b/common/src/main/java/io/wispforest/accessories/mixin/LivingEntityMixin.java @@ -13,8 +13,8 @@ import io.wispforest.accessories.api.events.extra.ExtraEventHandler; import io.wispforest.accessories.api.events.extra.OnTotemActivate; import io.wispforest.accessories.api.events.extra.OnTotemConsumption; -import io.wispforest.accessories.api.slot.SlotPredicateRegistry; import io.wispforest.accessories.api.slot.SlotReference; +import io.wispforest.accessories.api.slot.validator.SlotValidatorRegistry; import io.wispforest.accessories.data.EntitySlotLoader; import io.wispforest.accessories.impl.core.AccessoriesCapabilityImpl; import io.wispforest.accessories.impl.core.AccessoriesHolderImpl; @@ -24,7 +24,7 @@ import it.unimi.dsi.fastutil.objects.Reference2ObjectMap; import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap; import net.fabricmc.fabric.api.util.TriState; -import net.minecraft.Util; +import net.minecraft.util.Util; import net.minecraft.core.component.DataComponents; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; @@ -130,7 +130,7 @@ public void onEquipItem(SlotReference slotReference, ItemStack oldItem, ItemStac var level = this.level(); if (!ItemStack.isSameItemSameComponents(oldItem, newItem) && !this.firstTick && !level.isClientSide() && !this.isSpectator()) { - var isEquitableFor = newItem.isEmpty() || SlotPredicateRegistry.canInsertIntoSlot(newItem, slotReference); + var isEquitableFor = newItem.isEmpty() || SlotValidatorRegistry.canInsertIntoSlot(newItem, slotReference); if (!this.isSilent() && !newItem.isEmpty()) { var sound = AccessoryRegistry.getAccessoryOrDefault(newItem).getEquipSound(newItem, slotReference); diff --git a/common/src/main/java/io/wispforest/accessories/mixin/LivingEntityRenderMixin.java b/common/src/main/java/io/wispforest/accessories/mixin/LivingEntityRenderMixin.java index 14b78cca6..25a561bb1 100644 --- a/common/src/main/java/io/wispforest/accessories/mixin/LivingEntityRenderMixin.java +++ b/common/src/main/java/io/wispforest/accessories/mixin/LivingEntityRenderMixin.java @@ -11,7 +11,7 @@ import net.minecraft.client.renderer.entity.layers.RenderLayer; import net.minecraft.client.renderer.entity.state.EntityRenderState; import net.minecraft.client.renderer.entity.state.LivingEntityRenderState; -import net.minecraft.client.renderer.state.CameraRenderState; +import net.minecraft.client.renderer.state.level.CameraRenderState; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @@ -24,10 +24,10 @@ public abstract class LivingEntityRenderMixin { private void accessories$passCameraRenderState(RenderLayer instance, PoseStack poseStack, SubmitNodeCollector collector, int i, S s, float f, float g, Operation original, @Local(argsOnly = true) CameraRenderState cameraState) { var bl = instance instanceof AccessoriesRenderLayer; - if (bl) ((LivingEntityRenderState) s).setStateData(AccessoriesRenderStateKeys.CAMERA_STATE, cameraState); + if (bl) ((io.wispforest.accessories.pond.AccessoriesRenderStateAPImpl) s).setStateData(AccessoriesRenderStateKeys.CAMERA_STATE, cameraState); original.call(instance, poseStack, collector, i, s, f, g); - if (bl) ((LivingEntityRenderState) s).setStateData(AccessoriesRenderStateKeys.CAMERA_STATE, null); + if (bl) ((io.wispforest.accessories.pond.AccessoriesRenderStateAPImpl) s).setStateData(AccessoriesRenderStateKeys.CAMERA_STATE, null); } } diff --git a/common/src/main/java/io/wispforest/accessories/mixin/SimpleJsonResourceReloadListenerMixin.java b/common/src/main/java/io/wispforest/accessories/mixin/SimpleJsonResourceReloadListenerMixin.java index e561228e7..9e8880c19 100644 --- a/common/src/main/java/io/wispforest/accessories/mixin/SimpleJsonResourceReloadListenerMixin.java +++ b/common/src/main/java/io/wispforest/accessories/mixin/SimpleJsonResourceReloadListenerMixin.java @@ -10,7 +10,7 @@ import io.wispforest.accessories.pond.ReplaceableJsonResourceReloadListener; import io.wispforest.accessories.utils.JsonUtils; import net.minecraft.resources.FileToIdConverter; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.server.packs.resources.Resource; import net.minecraft.server.packs.resources.ResourceManager; import net.minecraft.server.packs.resources.SimpleJsonResourceReloadListener; @@ -36,11 +36,11 @@ public abstract class SimpleJsonResourceReloadListenerMixin implements Replaceab } @WrapOperation(method = "prepare(Lnet/minecraft/server/packs/resources/ResourceManager;Lnet/minecraft/util/profiling/ProfilerFiller;)Ljava/util/Map;", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/packs/resources/SimpleJsonResourceReloadListener;scanDirectory(Lnet/minecraft/server/packs/resources/ResourceManager;Lnet/minecraft/resources/FileToIdConverter;Lcom/mojang/serialization/DynamicOps;Lcom/mojang/serialization/Codec;Ljava/util/Map;)V")) - private void checkIfReplaceScan(ResourceManager resourceManager, FileToIdConverter converter, DynamicOps ops, Codec codec, Map output, Operation original) { + private void checkIfReplaceScan(ResourceManager resourceManager, FileToIdConverter converter, DynamicOps ops, Codec codec, Map output, Operation original) { // TODO: REPLACE WITH INJECTION INTO ORIGINAL SCAN?? if (this.allowReplacementLoading) { - converter = ((ContextedFileToIdConverter) converter) + converter = ((ContextedFileToIdConverter)(Object) converter) .setData(Accessories.of("allow_replacement_loading"), true); } @@ -49,8 +49,8 @@ private void checkIfReplaceScan(ResourceManager resourceManager, FileToIdCon @WrapOperation(method = "scanDirectory(Lnet/minecraft/server/packs/resources/ResourceManager;Lnet/minecraft/resources/FileToIdConverter;Lcom/mojang/serialization/DynamicOps;Lcom/mojang/serialization/Codec;Ljava/util/Map;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/resources/FileToIdConverter;listMatchingResources(Lnet/minecraft/server/packs/resources/ResourceManager;)Ljava/util/Map;")) - private static Map listReplacedResources(FileToIdConverter instance, ResourceManager resourceManager, Operation> original) { - if (instance instanceof ContextedFileToIdConverter ctx && ctx.getDataOrDefault(Accessories.of("allow_replacement_loading"), false)) { + private static Map listReplacedResources(FileToIdConverter instance, ResourceManager resourceManager, Operation> original) { + if ((Object)instance instanceof ContextedFileToIdConverter ctx && ctx.getDataOrDefault(Accessories.of("allow_replacement_loading"), false)) { return JsonUtils.scanDirectoryWithReplace(resourceManager, instance); } diff --git a/common/src/main/java/io/wispforest/accessories/mixin/StateHolderAccessor.java b/common/src/main/java/io/wispforest/accessories/mixin/StateHolderAccessor.java index dec7b3f8c..cb0e5b8b9 100644 --- a/common/src/main/java/io/wispforest/accessories/mixin/StateHolderAccessor.java +++ b/common/src/main/java/io/wispforest/accessories/mixin/StateHolderAccessor.java @@ -1,6 +1,5 @@ package io.wispforest.accessories.mixin; -import com.mojang.serialization.MapCodec; import net.minecraft.world.level.block.state.StateHolder; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; @@ -9,7 +8,4 @@ public interface StateHolderAccessor { @Accessor("owner") O accessories$owner(); - - @Accessor("propertiesCodec") - MapCodec accessories$propertiesCodec(); } diff --git a/common/src/main/java/io/wispforest/accessories/mixin/TooltipFlagMixin.java b/common/src/main/java/io/wispforest/accessories/mixin/TooltipFlagMixin.java index f9bf251a6..f6af7cc8d 100644 --- a/common/src/main/java/io/wispforest/accessories/mixin/TooltipFlagMixin.java +++ b/common/src/main/java/io/wispforest/accessories/mixin/TooltipFlagMixin.java @@ -1,10 +1,10 @@ package io.wispforest.accessories.mixin; -import io.wispforest.accessories.pond.TooltipFlagExtension; +import io.wispforest.accessories.pond.TooltipFlagExtended; import net.minecraft.world.item.TooltipFlag; import org.spongepowered.asm.mixin.Mixin; @Mixin(TooltipFlag.class) -public interface TooltipFlagMixin extends TooltipFlagExtension { +public interface TooltipFlagMixin extends TooltipFlagExtended { } diff --git a/common/src/main/java/io/wispforest/accessories/mixin/client/AbstractButtonMixin.java b/common/src/main/java/io/wispforest/accessories/mixin/client/AbstractButtonMixin.java index 7f0fdcc22..19411b5cb 100644 --- a/common/src/main/java/io/wispforest/accessories/mixin/client/AbstractButtonMixin.java +++ b/common/src/main/java/io/wispforest/accessories/mixin/client/AbstractButtonMixin.java @@ -20,8 +20,8 @@ public abstract class AbstractButtonMixin implements AbstractButtonExtension { return shouldCancel; }); -// @WrapOperation(method = "renderWidget", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/GuiGraphics;blitSprite(Ljava/util/function/Function;Lnet/minecraft/resources/ResourceLocation;IIIII)V")) -// private void adjustButtonRendering(GuiGraphics instance, Function function, ResourceLocation resourceLocation, int x, int y, int width, int height, int m, Operation original) { +// @WrapOperation(method = "renderWidget", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/GuiGraphics;blitSprite(Ljava/util/function/Function;Lnet/minecraft/resources/Identifier;IIIII)V")) +// private void adjustButtonRendering(GuiGraphicsExtractor instance, Function function, Identifier resourceLocation, int x, int y, int width, int height, int m, Operation original) { // boolean value = ADJUST_RENDERING_EVENT.invoker().render((AbstractButton) (Object) this, instance, resourceLocation, x, y, width, height); // // if(!value){ diff --git a/common/src/main/java/io/wispforest/accessories/mixin/client/AbstractContainerScreenAccessor.java b/common/src/main/java/io/wispforest/accessories/mixin/client/AbstractContainerScreenAccessor.java index 40b3d161b..e3a18ea2b 100644 --- a/common/src/main/java/io/wispforest/accessories/mixin/client/AbstractContainerScreenAccessor.java +++ b/common/src/main/java/io/wispforest/accessories/mixin/client/AbstractContainerScreenAccessor.java @@ -1,6 +1,7 @@ package io.wispforest.accessories.mixin.client; import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; +import net.minecraft.resources.Identifier; import net.minecraft.world.inventory.Slot; import net.minecraft.world.item.ItemStack; import org.jetbrains.annotations.Nullable; @@ -10,6 +11,12 @@ @Mixin(AbstractContainerScreen.class) public interface AbstractContainerScreenAccessor { + @Accessor("SLOT_HIGHLIGHT_FRONT_SPRITE") + static Identifier accessories$SLOT_HIGHLIGHT_FRONT_SPRITE() { throw new UnsupportedOperationException(); } + + @Accessor("SLOT_HIGHLIGHT_BACK_SPRITE") + static Identifier accessories$SLOT_HIGHLIGHT_BACK_SPRITE() { throw new UnsupportedOperationException(); } + @Accessor("leftPos") int accessories$leftPos(); @Accessor("topPos") int accessories$topPos(); diff --git a/common/src/main/java/io/wispforest/accessories/mixin/client/AbstractContainerScreenMixin.java b/common/src/main/java/io/wispforest/accessories/mixin/client/AbstractContainerScreenMixin.java index d7a534dbe..319409154 100644 --- a/common/src/main/java/io/wispforest/accessories/mixin/client/AbstractContainerScreenMixin.java +++ b/common/src/main/java/io/wispforest/accessories/mixin/client/AbstractContainerScreenMixin.java @@ -5,10 +5,10 @@ import com.mojang.blaze3d.pipeline.RenderPipeline; import io.wispforest.accessories.pond.ContainerScreenExtension; import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; import net.minecraft.data.AtlasIds; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.world.inventory.Slot; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -27,27 +27,31 @@ public abstract class AbstractContainerScreenMixin implements ContainerScreenExt if(override != null) cir.setReturnValue(override); } - @Inject(method = "renderSlot", at = @At(value = "HEAD"), cancellable = true) - private void accessories$shouldRenderSlot(GuiGraphics guiGraphics, Slot slot, CallbackInfo ci) { + @Inject(method = "extractSlot", at = @At(value = "HEAD"), cancellable = true) + private void accessories$shouldRenderSlot(GuiGraphicsExtractor guiGraphics, Slot slot, int x, int y, CallbackInfo ci) { var result = this.shouldRenderSlot(slot); if(result != null && !result) ci.cancel(); } - @WrapOperation(method = "renderSlot", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/GuiGraphics;blitSprite(Lcom/mojang/blaze3d/pipeline/RenderPipeline;Lnet/minecraft/resources/ResourceLocation;IIII)V")) - private void accessories$adjustFor18x18(GuiGraphics instance, RenderPipeline pipeline, ResourceLocation texture, int x, int y, int width, int height, Operation original) { - var textureAtlasSprite = Minecraft.getInstance().getAtlasManager() - .getAtlasOrThrow(AtlasIds.GUI) - .getSprite(texture); + @WrapOperation(method = "extractSlot", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/GuiGraphicsExtractor;blitSprite(Lcom/mojang/blaze3d/pipeline/RenderPipeline;Lnet/minecraft/resources/Identifier;IIII)V")) + private void accessories$adjustFor18x18(GuiGraphicsExtractor instance, RenderPipeline pipeline, Identifier texture, int x, int y, int width, int height, Operation original) { + var atlas = Minecraft.getInstance().getAtlasManager() + .getAtlasOrThrow(AtlasIds.GUI); - var is18x18 = textureAtlasSprite.contents().width() == 18 && textureAtlasSprite.contents().height() == 18; + var sprite = atlas.getSprite(texture); - if(is18x18) { - width = 18; - height = 18; + if (sprite != atlas.missingSprite()) { + var ctn = sprite.contents(); + var is18x18 = ctn.width() == 18 && ctn.height() == 18; - x = x - 1; - y = y - 1; + if(is18x18) { + width = 18; + height = 18; + + x = x - 1; + y = y - 1; + } } original.call(instance, pipeline, texture, x, y, width, height); diff --git a/common/src/main/java/io/wispforest/accessories/mixin/client/AbstractRecipeBookScreenMixin.java b/common/src/main/java/io/wispforest/accessories/mixin/client/AbstractRecipeBookScreenMixin.java index 31eb0ceb7..3b31442f5 100644 --- a/common/src/main/java/io/wispforest/accessories/mixin/client/AbstractRecipeBookScreenMixin.java +++ b/common/src/main/java/io/wispforest/accessories/mixin/client/AbstractRecipeBookScreenMixin.java @@ -10,7 +10,7 @@ @Mixin(AbstractRecipeBookScreen.class) public abstract class AbstractRecipeBookScreenMixin { - @Inject(method = "method_64513", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/components/Button;setPosition(II)V")) + @Inject(method = "init", at = @At(value = "TAIL")) private void updateLayout(CallbackInfo ci){ Layers.getInstances((AbstractRecipeBookScreen) (Object) this).forEach(Layer.Instance::dispatchLayoutUpdates); } diff --git a/common/src/main/java/io/wispforest/accessories/mixin/client/AvatarRendererMixin.java b/common/src/main/java/io/wispforest/accessories/mixin/client/AvatarRendererMixin.java index ba43124ca..d7e441227 100644 --- a/common/src/main/java/io/wispforest/accessories/mixin/client/AvatarRendererMixin.java +++ b/common/src/main/java/io/wispforest/accessories/mixin/client/AvatarRendererMixin.java @@ -8,14 +8,14 @@ import io.wispforest.accessories.pond.CosmeticArmorLookupTogglable; import net.minecraft.client.Minecraft; import net.minecraft.client.entity.ClientAvatarEntity; -import net.minecraft.client.model.PlayerModel; +import net.minecraft.client.model.player.PlayerModel; import net.minecraft.client.model.geom.ModelPart; import net.minecraft.client.renderer.SubmitNodeCollector; import net.minecraft.client.renderer.entity.EntityRendererProvider; import net.minecraft.client.renderer.entity.LivingEntityRenderer; import net.minecraft.client.renderer.entity.player.AvatarRenderer; import net.minecraft.client.renderer.entity.state.AvatarRenderState; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.world.entity.Avatar; import net.minecraft.world.entity.HumanoidArm; import org.spongepowered.asm.mixin.Mixin; @@ -38,12 +38,12 @@ public AvatarRendererMixin(EntityRendererProvider.Context context, PlayerModel m // } @WrapMethod(method = "renderHand") - public void accessories$cosmeticallyAdjustFirstPersonView(PoseStack poseStack, SubmitNodeCollector submitNodeCollector, int i, ResourceLocation resourceLocation, ModelPart modelPart, boolean bl, Operation original) { + public void accessories$cosmeticallyAdjustFirstPersonView(PoseStack poseStack, SubmitNodeCollector submitNodeCollector, int i, Identifier resourceLocation, ModelPart modelPart, boolean bl, Operation original) { CosmeticArmorLookupTogglable.runWithLookupToggle(Minecraft.getInstance().player, () -> original.call(poseStack, submitNodeCollector, i, resourceLocation, modelPart, bl)); } - @Inject(method = "renderHand", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/SubmitNodeCollector;submitModelPart(Lnet/minecraft/client/model/geom/ModelPart;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/RenderType;IILnet/minecraft/client/renderer/texture/TextureAtlasSprite;)V", shift = At.Shift.AFTER)) - private void accessories$firstPersonAccessories(PoseStack poseStack, SubmitNodeCollector submitNodeCollector, int combinedLight, ResourceLocation resourceLocation, ModelPart rendererArm, boolean bl, CallbackInfo ci, @Local PlayerModel playerModel) { + @Inject(method = "renderHand", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/SubmitNodeCollector;submitModelPart(Lnet/minecraft/client/model/geom/ModelPart;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/rendertype/RenderType;IILnet/minecraft/client/renderer/texture/TextureAtlasSprite;)V", shift = At.Shift.AFTER)) + private void accessories$firstPersonAccessories(PoseStack poseStack, SubmitNodeCollector submitNodeCollector, int combinedLight, Identifier resourceLocation, ModelPart rendererArm, boolean bl, CallbackInfo ci, @Local PlayerModel playerModel) { AccessoriesRenderLayer.submitFirstPersonAsClientPlayer((AvatarRenderer) (Object) this, playerModel, poseStack, combinedLight, submitNodeCollector, rendererArm == this.model.leftArm ? HumanoidArm.LEFT : HumanoidArm.RIGHT); } } \ No newline at end of file diff --git a/common/src/main/java/io/wispforest/accessories/mixin/client/ClientPacketListenerMixin.java b/common/src/main/java/io/wispforest/accessories/mixin/client/ClientPacketListenerMixin.java index 77fa197c1..ec353b5d1 100644 --- a/common/src/main/java/io/wispforest/accessories/mixin/client/ClientPacketListenerMixin.java +++ b/common/src/main/java/io/wispforest/accessories/mixin/client/ClientPacketListenerMixin.java @@ -15,7 +15,7 @@ public abstract class ClientPacketListenerMixin { @ModifyReturnValue(method = "findTotem", at = @At(value = "RETURN", ordinal = 1)) private static ItemStack accessories$findPossibleTotem(ItemStack original, @Local(argsOnly = true) Player player) { - var capability = player.accessoriesCapability(); + var capability = ((io.wispforest.accessories.pond.AccessoriesAPIAccess) player).accessoriesCapability(); if (capability != null) { var totem = capability.getFirstEquipped(ItemStackBasedPredicate.ofComponents("totem_check", DataComponents.DEATH_PROTECTION)); diff --git a/common/src/main/java/io/wispforest/accessories/mixin/client/CreativeInventoryScreenMixin.java b/common/src/main/java/io/wispforest/accessories/mixin/client/CreativeInventoryScreenMixin.java index 09f0bf6ed..e4e6914ec 100644 --- a/common/src/main/java/io/wispforest/accessories/mixin/client/CreativeInventoryScreenMixin.java +++ b/common/src/main/java/io/wispforest/accessories/mixin/client/CreativeInventoryScreenMixin.java @@ -9,7 +9,7 @@ import net.minecraft.client.gui.screens.inventory.CreativeModeInventoryScreen; import net.minecraft.network.chat.Component; import net.minecraft.world.entity.player.Inventory; -import net.minecraft.world.inventory.ClickType; +import net.minecraft.world.inventory.ContainerInput; import net.minecraft.world.inventory.Slot; import net.minecraft.world.item.CreativeModeTab; import org.spongepowered.asm.mixin.Mixin; @@ -45,7 +45,7 @@ private void onCreativeTagChange(CreativeModeTab tab, CallbackInfo ci){ } @Inject(method = "slotClicked", at = @At(value = "INVOKE", target = "Lnet/minecraft/core/NonNullList;size()I", ordinal = 0, shift = At.Shift.BEFORE)) - private void clearAccessoriesWithClearSlot(Slot slot, int slotId, int mouseButton, ClickType type, CallbackInfo ci) { + private void clearAccessoriesWithClearSlot(Slot slot, int slotId, int mouseButton, ContainerInput type, CallbackInfo ci) { if(this.nukeCoolDown <= 0) { AccessoriesNetworking.sendToServer(new NukeAccessories()); diff --git a/common/src/main/java/io/wispforest/accessories/mixin/client/DefaultTooltipPositionerMixin.java b/common/src/main/java/io/wispforest/accessories/mixin/client/DefaultTooltipPositionerMixin.java index 5c431a6ac..60d6c9dea 100644 --- a/common/src/main/java/io/wispforest/accessories/mixin/client/DefaultTooltipPositionerMixin.java +++ b/common/src/main/java/io/wispforest/accessories/mixin/client/DefaultTooltipPositionerMixin.java @@ -1,20 +1,48 @@ package io.wispforest.accessories.mixin.client; +import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import io.wispforest.accessories.client.gui.AccessoriesScreenBase; +import io.wispforest.accessories.pond.DefaultTooltipPositionerExt; import net.minecraft.client.gui.screens.inventory.tooltip.DefaultTooltipPositioner; +import org.jetbrains.annotations.Nullable; import org.joml.Vector2i; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import java.util.function.UnaryOperator; + @Mixin(DefaultTooltipPositioner.class) -public abstract class DefaultTooltipPositionerMixin { +public abstract class DefaultTooltipPositionerMixin implements DefaultTooltipPositionerExt { + + private @Nullable PositionAdjuster adjuster = null; + + @Invoker("") + public static DefaultTooltipPositioner accessories$createPositioner() { + throw new IllegalStateException(); + } + + @WrapMethod(method = "positionTooltip(IILorg/joml/Vector2i;II)V") + private void accessories$forceLeftPositioning(int screenWidth, int screenHeight, Vector2i tooltipPos, int tooltipWidth, int tooltipHeight, Operation original) { + if (adjuster != null) adjuster.adjust(screenWidth, tooltipPos, tooltipWidth); + + original.call(screenWidth, screenHeight, tooltipPos, tooltipWidth, tooltipHeight); + } + + @Override + public void accessories$setOperator(PositionAdjuster adjuster) { + this.adjuster = adjuster; + } + + @Override + public DefaultTooltipPositioner accessories$copyWith(PositionAdjuster adjuster) { + var positioner = accessories$createPositioner(); + + ((DefaultTooltipPositionerExt) positioner).accessories$setOperator(adjuster); - @Inject(method = "positionTooltip(IILorg/joml/Vector2i;II)V", at = @At(value = "HEAD")) - private void accessories$forceLeftPositioning(int screenWidth, int screenHeight, Vector2i tooltipPos, int tooltipWidth, int tooltipHeight, CallbackInfo ci) { - if (tooltipPos.x + tooltipWidth <= screenWidth && AccessoriesScreenBase.FORCE_TOOLTIP_LEFT.getValue()) { - tooltipPos.x = Math.max(tooltipPos.x - 24 - tooltipWidth, 4); - } + return positioner; } } \ No newline at end of file diff --git a/common/src/main/java/io/wispforest/accessories/mixin/client/GuiGraphicsAccessor.java b/common/src/main/java/io/wispforest/accessories/mixin/client/GuiGraphicsAccessor.java new file mode 100644 index 000000000..6f7f6e230 --- /dev/null +++ b/common/src/main/java/io/wispforest/accessories/mixin/client/GuiGraphicsAccessor.java @@ -0,0 +1,20 @@ +package io.wispforest.accessories.mixin.client; + +import net.minecraft.client.gui.Font; +import net.minecraft.client.gui.GuiGraphicsExtractor; +import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent; +import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipPositioner; +import net.minecraft.resources.Identifier; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +import java.util.List; + +@Mixin(GuiGraphicsExtractor.class) +public interface GuiGraphicsAccessor { + @Invoker("setTooltipForNextFrameInternal") + void accessories$setTooltipForNextFrameInternal( + Font font, List components, int x, int y, ClientTooltipPositioner positioner, @Nullable Identifier background, boolean focused + ); +} diff --git a/common/src/main/java/io/wispforest/accessories/mixin/client/GuiGraphicsMixin.java b/common/src/main/java/io/wispforest/accessories/mixin/client/GuiGraphicsMixin.java index c64b74973..50c23e830 100644 --- a/common/src/main/java/io/wispforest/accessories/mixin/client/GuiGraphicsMixin.java +++ b/common/src/main/java/io/wispforest/accessories/mixin/client/GuiGraphicsMixin.java @@ -1,29 +1,84 @@ package io.wispforest.accessories.mixin.client; +import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.llamalad7.mixinextras.sugar.Local; +import io.wispforest.accessories.api.client.tooltip.DeferredTooltip; +import io.wispforest.accessories.client.gui.AccessoriesScreenBase; +import io.wispforest.accessories.pond.DefaultTooltipPositionerExt; +import io.wispforest.accessories.pond.DeferredTooltipGetter; +import io.wispforest.accessories.pond.GuiGraphicsAccess; import io.wispforest.accessories.pond.ScissorStackManipulation; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.Font; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.gui.navigation.ScreenRectangle; +import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent; +import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipPositioner; +import net.minecraft.client.gui.screens.inventory.tooltip.DefaultTooltipPositioner; +import net.minecraft.client.renderer.state.gui.GuiRenderState; +import net.minecraft.resources.Identifier; import org.jetbrains.annotations.Nullable; +import org.objectweb.asm.Opcodes; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.gen.Accessor; +import org.spongepowered.asm.mixin.injection.At; import java.util.ArrayDeque; import java.util.Deque; +import java.util.List; -@Mixin(GuiGraphics.class) -public abstract class GuiGraphicsMixin implements ScissorStackManipulation { +@Mixin(GuiGraphicsExtractor.class) +public abstract class GuiGraphicsMixin implements ScissorStackManipulation, GuiGraphicsAccess, DeferredTooltipGetter { @Accessor("scissorStack") - public abstract GuiGraphics.ScissorStack accessories$scissorStack(); + public abstract GuiGraphicsExtractor.ScissorStack accessories$scissorStack(); + + @Accessor("guiRenderState") + public abstract GuiRenderState accessories$guiRenderState(); + + @Shadow + private @Nullable Runnable deferredTooltip; @Override public void accessories$renderWithoutEntries(Runnable runnable, @Nullable Integer levels) { ((ScissorStackManipulation) this.accessories$scissorStack()).accessories$renderWithoutEntries(runnable, levels); } - @Mixin(GuiGraphics.ScissorStack.class) + @WrapMethod(method = "setTooltipForNextFrameInternal") + private void accessories$adjustPositioner(Font font, List components, int x, int y, ClientTooltipPositioner positioner, @Nullable Identifier background, boolean focused, Operation original) { + // TODO: MAYBE GOOD IDEA TO CHECK AGAINST REFERENCE OF THE SINGULAR USED INSTANCE + if (positioner instanceof DefaultTooltipPositioner defaultTooltipPositioner) { + var basePositioner = AccessoriesScreenBase.ALTERATIVE_POSITIONER.getValue(); + + if (basePositioner != null) { + positioner = DefaultTooltipPositionerExt.copyWith(defaultTooltipPositioner, basePositioner); + } + } + + original.call(font, components, x, y, positioner, background, focused); + } + + @WrapOperation(method = "setTooltipForNextFrameInternal", at = @At(value = "FIELD", target = "Lnet/minecraft/client/gui/GuiGraphicsExtractor;deferredTooltip:Ljava/lang/Runnable;", opcode = Opcodes.PUTFIELD)) + private void accessories$wrapTooltipRenderCall(GuiGraphicsExtractor instance, Runnable value, Operation original, + @Local(argsOnly = true) Font font, + @Local(argsOnly = true) List components, + @Local(argsOnly = true, ordinal = 0) int x, + @Local(argsOnly = true, ordinal = 1) int y, + @Local(argsOnly = true) ClientTooltipPositioner positioner, + @Local(argsOnly = true) @Nullable Identifier background, + @Local(argsOnly = true) boolean focused) { + original.call(instance, new DeferredTooltip(font, components, x, y, positioner, background, focused, value)); + } + + @Override + public @Nullable DeferredTooltip accessories$getTooltip() { + return this.deferredTooltip instanceof DeferredTooltip tooltip ? tooltip : null; + } + + @Mixin(GuiGraphicsExtractor.ScissorStack.class) public abstract static class ScissorStackMixin implements ScissorStackManipulation { @Accessor("stack") public abstract Deque accessories$stack(); diff --git a/common/src/main/java/io/wispforest/accessories/mixin/client/InventoryScreenMixin.java b/common/src/main/java/io/wispforest/accessories/mixin/client/InventoryScreenMixin.java index 63b90ff84..c69bfed4d 100644 --- a/common/src/main/java/io/wispforest/accessories/mixin/client/InventoryScreenMixin.java +++ b/common/src/main/java/io/wispforest/accessories/mixin/client/InventoryScreenMixin.java @@ -3,19 +3,17 @@ import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod; import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import io.wispforest.accessories.pond.CosmeticArmorLookupTogglable; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.gui.screens.inventory.InventoryScreen; import net.minecraft.world.entity.LivingEntity; -import org.joml.Quaternionf; -import org.joml.Vector3f; import org.spongepowered.asm.mixin.Mixin; @Mixin(InventoryScreen.class) public abstract class InventoryScreenMixin { - @WrapMethod(method = "renderEntityInInventory") - private static void accessories$wrapWithArmorLookup(GuiGraphics guiGraphics, int i, int j, int k, int l, float f, Vector3f vector3f, Quaternionf quaternionf, Quaternionf quaternionf2, LivingEntity livingEntity, Operation original) { - CosmeticArmorLookupTogglable.runWithLookupToggle(livingEntity, () -> { - original.call(guiGraphics, i, j, k, l, f, vector3f, quaternionf, quaternionf2, livingEntity); + @WrapMethod(method = "extractEntityInInventoryFollowsMouse") + private static void accessories$wrapWithArmorLookup(GuiGraphicsExtractor guiGraphics, int x1, int y1, int x2, int y2, int scale, float yOffset, float mouseX, float mouseY, LivingEntity entity, Operation original) { + CosmeticArmorLookupTogglable.runWithLookupToggle(entity, () -> { + original.call(guiGraphics, x1, y1, x2, y2, scale, yOffset, mouseX, mouseY, entity); }); } } diff --git a/common/src/main/java/io/wispforest/accessories/mixin/client/MinecraftMixin.java b/common/src/main/java/io/wispforest/accessories/mixin/client/MinecraftMixin.java index 3cd6c29af..1c9bd2fc5 100644 --- a/common/src/main/java/io/wispforest/accessories/mixin/client/MinecraftMixin.java +++ b/common/src/main/java/io/wispforest/accessories/mixin/client/MinecraftMixin.java @@ -9,7 +9,7 @@ @Mixin(Minecraft.class) public abstract class MinecraftMixin { - @Inject(method = "resizeDisplay", at = @At(value = "TAIL")) + @Inject(method = "resizeGui", at = @At(value = "TAIL")) private void captureResize(CallbackInfo ci){ var client = ((Minecraft) ((Object) this)); AccessoriesClient.WINDOW_RESIZE_CALLBACK_EVENT.invoker().onResized(client, client.getWindow()); diff --git a/common/src/main/java/io/wispforest/accessories/mixin/client/RenderPhaseMixin.java b/common/src/main/java/io/wispforest/accessories/mixin/client/RenderPhaseMixin.java deleted file mode 100644 index 6e3a1a40a..000000000 --- a/common/src/main/java/io/wispforest/accessories/mixin/client/RenderPhaseMixin.java +++ /dev/null @@ -1,20 +0,0 @@ -package io.wispforest.accessories.mixin.client; - -import com.llamalad7.mixinextras.injector.ModifyExpressionValue; -import com.mojang.blaze3d.pipeline.RenderTarget; -import io.wispforest.accessories.client.AccessoriesFunkyRenderingState; -import io.wispforest.accessories.client.AccessoriesPipelines; -import net.minecraft.client.renderer.RenderStateShard; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; - -@Mixin(RenderStateShard.class) -public abstract class RenderPhaseMixin { - - @ModifyExpressionValue(method = "method_68490", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Minecraft;getMainRenderTarget()Lcom/mojang/blaze3d/pipeline/RenderTarget;")) - private static RenderTarget injectProperRenderTarget(RenderTarget original) { - return (AccessoriesFunkyRenderingState.INSTANCE.isOverrideRenderTarget()) - ? AccessoriesPipelines.getOrCreateBuffer() - : original; - } -} diff --git a/common/src/main/java/io/wispforest/accessories/mixin/client/owo/BaseParentComponentMixin.java b/common/src/main/java/io/wispforest/accessories/mixin/client/owo/BaseParentComponentMixin.java index 69bdfdd7e..b1bb34f1a 100644 --- a/common/src/main/java/io/wispforest/accessories/mixin/client/owo/BaseParentComponentMixin.java +++ b/common/src/main/java/io/wispforest/accessories/mixin/client/owo/BaseParentComponentMixin.java @@ -4,27 +4,27 @@ import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import io.wispforest.accessories.client.gui.AccessoriesScreen; import io.wispforest.accessories.client.gui.components.ComponentUtils; -import io.wispforest.owo.ui.base.BaseParentComponent; -import io.wispforest.owo.ui.core.OwoUIDrawContext; -import io.wispforest.owo.ui.core.ParentComponent; +import io.wispforest.owo.ui.base.BaseParentUIComponent; +import io.wispforest.owo.ui.core.OwoUIGraphics; +import io.wispforest.owo.ui.core.ParentUIComponent; import io.wispforest.owo.ui.core.PositionedRectangle; import io.wispforest.owo.util.pond.OwoSlotExtension; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; -@Mixin(value = BaseParentComponent.class, remap = false) +@Mixin(value = BaseParentUIComponent.class, remap = false) public abstract class BaseParentComponentMixin { //-- - @WrapOperation(method = "drawChildren", at = @At(value = "INVOKE", target = "Lio/wispforest/owo/ui/core/OwoUIDrawContext;intersectsScissor(Lio/wispforest/owo/ui/core/PositionedRectangle;)Z")) - private boolean disableSlotsNotDrawn(OwoUIDrawContext instance, PositionedRectangle other, Operation original) { + @WrapOperation(method = "drawChildren", at = @At(value = "INVOKE", target = "Lio/wispforest/owo/ui/core/OwoUIGraphics;intersectsScissor(Lio/wispforest/owo/ui/core/PositionedRectangle;)Z")) + private boolean disableSlotsNotDrawn(OwoUIGraphics instance, PositionedRectangle other, Operation original) { var result = original.call(instance, other); if (!result) { if (other instanceof AccessoriesScreen.ExtendedSlotComponent slotComponent) { ((OwoSlotExtension) slotComponent.slot()).owo$setDisabledOverride(true); - } else if (other instanceof ParentComponent parentComponent) { + } else if (other instanceof ParentUIComponent parentComponent) { ComponentUtils.recursiveSearch(parentComponent, AccessoriesScreen.ExtendedSlotComponent.class, slotComponent -> { ((OwoSlotExtension) slotComponent.slot()).owo$setDisabledOverride(true); }); diff --git a/common/src/main/java/io/wispforest/accessories/mixin/client/owo/OwoReiPluginMixin.java b/common/src/main/java/io/wispforest/accessories/mixin/client/owo/OwoReiPluginMixin.java index 7e7c6430c..ddd20ca1c 100644 --- a/common/src/main/java/io/wispforest/accessories/mixin/client/owo/OwoReiPluginMixin.java +++ b/common/src/main/java/io/wispforest/accessories/mixin/client/owo/OwoReiPluginMixin.java @@ -2,7 +2,7 @@ import io.wispforest.accessories.client.gui.AccessoriesScreen; import io.wispforest.owo.compat.rei.OwoReiPlugin; -import io.wispforest.owo.ui.base.BaseOwoHandledScreen; +import io.wispforest.owo.ui.base.BaseOwoContainerScreen; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -15,7 +15,7 @@ public abstract class OwoReiPluginMixin { @Inject(method = "lambda$registerExclusionZones$2", at = @At("HEAD"), remap = false, cancellable = true) - private static void accessories$preventZonesForAccessoriesScreen(BaseOwoHandledScreen screen, CallbackInfoReturnable cir) { + private static void accessories$preventZonesForAccessoriesScreen(BaseOwoContainerScreen screen, CallbackInfoReturnable cir) { if(screen instanceof AccessoriesScreen) cir.setReturnValue(List.of()); } } diff --git a/common/src/main/java/io/wispforest/accessories/mixin/client/owo/ScrollContainerMixin.java b/common/src/main/java/io/wispforest/accessories/mixin/client/owo/ScrollContainerMixin.java index 204e61d36..753750f47 100644 --- a/common/src/main/java/io/wispforest/accessories/mixin/client/owo/ScrollContainerMixin.java +++ b/common/src/main/java/io/wispforest/accessories/mixin/client/owo/ScrollContainerMixin.java @@ -2,9 +2,9 @@ import io.wispforest.accessories.client.gui.components.ExtendedScrollContainer; import io.wispforest.owo.ui.container.ScrollContainer; -import io.wispforest.owo.ui.container.WrappingParentComponent; -import io.wispforest.owo.ui.core.Component; -import io.wispforest.owo.ui.core.OwoUIDrawContext; +import io.wispforest.owo.ui.container.WrappingParentUIComponent; +import io.wispforest.owo.ui.core.UIComponent; +import io.wispforest.owo.ui.core.OwoUIGraphics; import io.wispforest.owo.ui.core.Sizing; import org.objectweb.asm.Opcodes; import org.spongepowered.asm.mixin.Final; @@ -15,7 +15,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(value = ScrollContainer.class, remap = false) -public abstract class ScrollContainerMixin extends WrappingParentComponent { +public abstract class ScrollContainerMixin extends WrappingParentUIComponent { @Shadow @Final protected ScrollContainer.ScrollDirection direction; @Shadow protected int scrollbarOffset; @@ -25,7 +25,7 @@ protected ScrollContainerMixin(Sizing horizontalSizing, Sizing verticalSizing, C } @Inject(method = "draw", at = @At(value = "JUMP", opcode = Opcodes.IF_ACMPNE, ordinal = 2), remap = false) - private void adjustOffsetForExtendedScrollContainer(OwoUIDrawContext context, int mouseX, int mouseY, float partialTicks, float delta, CallbackInfo ci) { + private void adjustOffsetForExtendedScrollContainer(OwoUIGraphics context, int mouseX, int mouseY, float partialTicks, float delta, CallbackInfo ci) { if(((ScrollContainer) (Object) this) instanceof ExtendedScrollContainer extendedScrollContainer && extendedScrollContainer.oppositeScrollbar()) { this.scrollbarOffset = this.direction == ScrollContainer.ScrollDirection.VERTICAL ? this.x() : this.y(); } diff --git a/common/src/main/java/io/wispforest/accessories/networking/client/AccessoryBreak.java b/common/src/main/java/io/wispforest/accessories/networking/client/AccessoryBreak.java index 928ed5639..f3df1e0e8 100644 --- a/common/src/main/java/io/wispforest/accessories/networking/client/AccessoryBreak.java +++ b/common/src/main/java/io/wispforest/accessories/networking/client/AccessoryBreak.java @@ -31,7 +31,7 @@ public static void handlePacket(AccessoryBreak packet, Player player) { var slotReference = SlotReference.of(livingEntity, packet.slotName(), packet.slotIndex()); - var capability = livingEntity.accessoriesCapability(); + var capability = ((io.wispforest.accessories.pond.AccessoriesAPIAccess) livingEntity).accessoriesCapability(); var container = capability.getContainer(slotReference.type()); diff --git a/common/src/main/java/io/wispforest/accessories/networking/client/SyncServerOverrideOption.java b/common/src/main/java/io/wispforest/accessories/networking/client/SyncServerOverrideOption.java index 36540d79b..6dce1da88 100644 --- a/common/src/main/java/io/wispforest/accessories/networking/client/SyncServerOverrideOption.java +++ b/common/src/main/java/io/wispforest/accessories/networking/client/SyncServerOverrideOption.java @@ -24,7 +24,7 @@ public record SyncServerOverrideOption(String configId, Option.Key optionKey, Fr public static final StructEndec ENDEC = StructEndecBuilder.of( Endec.STRING.fieldOf("config_id", SyncServerOverrideOption::configId), Endec.STRING.xmap(Option.Key::new, Option.Key::asString).fieldOf("option_key", SyncServerOverrideOption::optionKey), - MinecraftEndecs.PACKET_BYTE_BUF.fieldOf("buf", SyncServerOverrideOption::buf), + MinecraftEndecs.FRIENDLY_BYTE_BUF.fieldOf("buf", SyncServerOverrideOption::buf), SyncServerOverrideOption::new ); diff --git a/common/src/main/java/io/wispforest/accessories/networking/server/NukeAccessories.java b/common/src/main/java/io/wispforest/accessories/networking/server/NukeAccessories.java index 82ed92674..fb92f5384 100644 --- a/common/src/main/java/io/wispforest/accessories/networking/server/NukeAccessories.java +++ b/common/src/main/java/io/wispforest/accessories/networking/server/NukeAccessories.java @@ -20,7 +20,7 @@ public static void handlePacket(NukeAccessories packet, Player player) { return; } - var cap = player.accessoriesCapability(); + var cap = ((io.wispforest.accessories.pond.AccessoriesAPIAccess) player).accessoriesCapability(); if (cap != null) { cap.reset(false); diff --git a/common/src/main/java/io/wispforest/accessories/networking/server/ScreenOpen.java b/common/src/main/java/io/wispforest/accessories/networking/server/ScreenOpen.java index e6a18ed9d..89d2388cf 100644 --- a/common/src/main/java/io/wispforest/accessories/networking/server/ScreenOpen.java +++ b/common/src/main/java/io/wispforest/accessories/networking/server/ScreenOpen.java @@ -7,6 +7,7 @@ import io.wispforest.endec.impl.StructEndecBuilder; import io.wispforest.owo.serialization.endec.MinecraftEndecs; import net.minecraft.server.level.ServerPlayer; +import net.minecraft.server.players.NameAndId; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; @@ -41,7 +42,7 @@ public static void handlePacket(ScreenOpen packet, Player player) { livingEntity = living; var bl = !player.equals(livingEntity) - && player.getPermissionLevel() == 0 + && !(player instanceof ServerPlayer sp && sp.level().getServer().getPlayerList().isOp(new NameAndId(sp.getGameProfile()))) && player.entityInteractionRange() < player.distanceTo(livingEntity); // Prevent people without op perms to have the ability to open inv from any distance diff --git a/common/src/main/java/io/wispforest/accessories/networking/server/SyncCosmeticToggle.java b/common/src/main/java/io/wispforest/accessories/networking/server/SyncCosmeticToggle.java index e302d9894..9c3ef940b 100644 --- a/common/src/main/java/io/wispforest/accessories/networking/server/SyncCosmeticToggle.java +++ b/common/src/main/java/io/wispforest/accessories/networking/server/SyncCosmeticToggle.java @@ -40,7 +40,7 @@ public static void handlePacket(SyncCosmeticToggle packet, Player player) { if(!result.orElse(false)) return; } - var capability = targetEntity.accessoriesCapability(); + var capability = ((io.wispforest.accessories.pond.AccessoriesAPIAccess) targetEntity).accessoriesCapability(); if(capability == null) return; diff --git a/common/src/main/java/io/wispforest/accessories/pond/ContextedFileToIdConverter.java b/common/src/main/java/io/wispforest/accessories/pond/ContextedFileToIdConverter.java index e6541f02a..3f232ec0f 100644 --- a/common/src/main/java/io/wispforest/accessories/pond/ContextedFileToIdConverter.java +++ b/common/src/main/java/io/wispforest/accessories/pond/ContextedFileToIdConverter.java @@ -1,15 +1,15 @@ package io.wispforest.accessories.pond; import net.minecraft.resources.FileToIdConverter; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import org.jetbrains.annotations.Nullable; public interface ContextedFileToIdConverter { - FileToIdConverter setData(ResourceLocation location, T t); + FileToIdConverter setData(Identifier location, T t); - @Nullable T getData(ResourceLocation location); + @Nullable T getData(Identifier location); - default T getDataOrDefault(ResourceLocation location, T defaultValue) { + default T getDataOrDefault(Identifier location, T defaultValue) { var data = (T) getData(location); if (data == null) data = defaultValue; diff --git a/common/src/main/java/io/wispforest/accessories/pond/DefaultTooltipPositionerExt.java b/common/src/main/java/io/wispforest/accessories/pond/DefaultTooltipPositionerExt.java new file mode 100644 index 000000000..af6ad61e4 --- /dev/null +++ b/common/src/main/java/io/wispforest/accessories/pond/DefaultTooltipPositionerExt.java @@ -0,0 +1,21 @@ +package io.wispforest.accessories.pond; + +import net.minecraft.client.gui.screens.inventory.tooltip.DefaultTooltipPositioner; +import org.joml.Vector2i; + +import java.util.function.UnaryOperator; + +public interface DefaultTooltipPositionerExt { + + static DefaultTooltipPositioner copyWith(DefaultTooltipPositioner positioner, PositionAdjuster adjuster) { + return ((DefaultTooltipPositionerExt) positioner).accessories$copyWith(adjuster); + } + + DefaultTooltipPositioner accessories$copyWith(PositionAdjuster adjuster); + + void accessories$setOperator(PositionAdjuster adjuster); + + interface PositionAdjuster { + void adjust(int screenWidth, Vector2i tooltipPos, int tooltipWidth); + } +} diff --git a/common/src/main/java/io/wispforest/accessories/pond/DeferredTooltipGetter.java b/common/src/main/java/io/wispforest/accessories/pond/DeferredTooltipGetter.java new file mode 100644 index 000000000..e141f980a --- /dev/null +++ b/common/src/main/java/io/wispforest/accessories/pond/DeferredTooltipGetter.java @@ -0,0 +1,8 @@ +package io.wispforest.accessories.pond; + +import io.wispforest.accessories.api.client.tooltip.DeferredTooltip; +import org.jetbrains.annotations.Nullable; + +public interface DeferredTooltipGetter { + @Nullable DeferredTooltip accessories$getTooltip(); +} diff --git a/common/src/main/java/io/wispforest/accessories/pond/GuiGraphicsAccess.java b/common/src/main/java/io/wispforest/accessories/pond/GuiGraphicsAccess.java new file mode 100644 index 000000000..777159487 --- /dev/null +++ b/common/src/main/java/io/wispforest/accessories/pond/GuiGraphicsAccess.java @@ -0,0 +1,9 @@ +package io.wispforest.accessories.pond; + +import net.minecraft.client.gui.GuiGraphicsExtractor; +import net.minecraft.client.renderer.state.gui.GuiRenderState; + +public interface GuiGraphicsAccess { + GuiRenderState accessories$guiRenderState(); + GuiGraphicsExtractor.ScissorStack accessories$scissorStack(); +} diff --git a/common/src/main/java/io/wispforest/accessories/pond/TooltipFlagExtended.java b/common/src/main/java/io/wispforest/accessories/pond/TooltipFlagExtended.java new file mode 100644 index 000000000..f5fc864f5 --- /dev/null +++ b/common/src/main/java/io/wispforest/accessories/pond/TooltipFlagExtended.java @@ -0,0 +1,85 @@ +package io.wispforest.accessories.pond; + +import io.wispforest.accessories.AccessoriesClientInternals; +import net.minecraft.util.Util; +import net.minecraft.world.item.TooltipFlag; + +public interface TooltipFlagExtended { + default boolean hasControlDown() { + return false; + } + + default boolean hasShiftDown() { + return false; + } + + default boolean hasAltDown() { + return false; + } + + default int getModifiers() { + return 0; + } + + default TooltipFlag getInnerFlag() { + return TooltipFlag.NORMAL; + } + + default TooltipFlag withMask(int modifiers) { + return new NestedTooltipFlag((TooltipFlag) this, modifiers); + } + + default TooltipFlag withMask() { + return new NestedTooltipFlag((TooltipFlag) this, AccessoriesClientInternals.getInstance().createBitFlag()); + } + + static TooltipFlag create() { + return AccessoriesClientInternals.getInstance().createTooltipFlag(); + } + + static TooltipFlag create(boolean isAdvanced) { + return new NestedTooltipFlag(isAdvanced ? TooltipFlag.Default.ADVANCED : TooltipFlag.Default.NORMAL, AccessoriesClientInternals.getInstance().createBitFlag()); + } +} + +record NestedTooltipFlag(TooltipFlag flag, int modifiers) implements TooltipFlag, TooltipFlagExtended { + + private static final boolean IS_OSX = Util.getPlatform() == Util.OS.OSX; + private static final int EDIT_SHORTCUT_KEY_MODIFIER = IS_OSX ? 8 : 2; + + @Override + public boolean isAdvanced() { + return flag.isAdvanced(); + } + + @Override + public boolean isCreative() { + return flag.isCreative(); + } + + @Override + public boolean hasAltDown() { + return (this.getModifiers() & 4) != 0; + } + + @Override + public boolean hasShiftDown() { + return (this.getModifiers() & 1) != 0; + } + + @Override + public boolean hasControlDown() { + return (this.getModifiers() & EDIT_SHORTCUT_KEY_MODIFIER) != 0; + } + + public int getModifiers() { + return modifiers; + } + + @Override + public TooltipFlag getInnerFlag() { + var baseFlag = ((TooltipFlagExtended) flag).getInnerFlag(); + + return (baseFlag instanceof NestedTooltipFlag nestedFlag) ? nestedFlag.getInnerFlag() : baseFlag; + } +} diff --git a/common/src/main/java/io/wispforest/accessories/pond/TooltipFlagExtension.java b/common/src/main/java/io/wispforest/accessories/pond/TooltipFlagExtension.java deleted file mode 100644 index bf2dc4579..000000000 --- a/common/src/main/java/io/wispforest/accessories/pond/TooltipFlagExtension.java +++ /dev/null @@ -1,66 +0,0 @@ -package io.wispforest.accessories.pond; - -import net.minecraft.Util; -import net.minecraft.client.input.InputQuirks; -import net.minecraft.world.item.TooltipFlag; - -public interface TooltipFlagExtension { - default boolean hasControlDown() { - return false; - } - - default boolean hasShiftDown() { - return false; - } - - default boolean hasAltDown() { - return false; - } - - default int getModifiers() { - return 0; - } - - default TooltipFlag getInnerFlag() { - return TooltipFlag.NORMAL; - } - - static TooltipFlag createFlag(TooltipFlag flag, int modifiers) { - return new TooltipFlag() { - static final boolean IS_OSX = Util.getPlatform() == Util.OS.OSX; - static final int EDIT_SHORTCUT_KEY_MODIFIER = IS_OSX ? 8 : 2; - @Override - public boolean isAdvanced() { - return flag.isAdvanced(); - } - - @Override - public boolean isCreative() { - return flag.isCreative(); - } - - @Override - public boolean hasAltDown() { - return (this.getModifiers() & 4) != 0; - } - - @Override - public boolean hasShiftDown() { - return (this.getModifiers() & 1) != 0; - } - - @Override - public boolean hasControlDown() { - return (this.getModifiers() & EDIT_SHORTCUT_KEY_MODIFIER) != 0; - } - - public int getModifiers() { - return modifiers; - } - - public TooltipFlag getInnerFlag() { - return TooltipFlag.NORMAL; - } - }; - } -} diff --git a/common/src/main/java/io/wispforest/accessories/utils/AttributeUtils.java b/common/src/main/java/io/wispforest/accessories/utils/AttributeUtils.java index cd69ebe50..192fde4ee 100644 --- a/common/src/main/java/io/wispforest/accessories/utils/AttributeUtils.java +++ b/common/src/main/java/io/wispforest/accessories/utils/AttributeUtils.java @@ -17,7 +17,7 @@ public static void addTransientAttributeModifiers(LivingEntity livingEntity, Acc if(attributes.isEmpty()) return; var attributeMap = livingEntity.getAttributes(); - var capability = livingEntity.accessoriesCapability(); + var capability = ((io.wispforest.accessories.pond.AccessoriesAPIAccess) livingEntity).accessoriesCapability(); var containers = capability.getContainers(); @@ -46,7 +46,7 @@ public static void removeTransientAttributeModifiers(LivingEntity livingEntity, if(attributes.isEmpty()) return; var attributeMap = livingEntity.getAttributes(); - var capability = livingEntity.accessoriesCapability(); + var capability = ((io.wispforest.accessories.pond.AccessoriesAPIAccess) livingEntity).accessoriesCapability(); var containers = capability.getContainers(); diff --git a/common/src/main/java/io/wispforest/accessories/utils/BaseContainer.java b/common/src/main/java/io/wispforest/accessories/utils/BaseContainer.java index fca2426bf..60efbfc67 100644 --- a/common/src/main/java/io/wispforest/accessories/utils/BaseContainer.java +++ b/common/src/main/java/io/wispforest/accessories/utils/BaseContainer.java @@ -5,7 +5,7 @@ import net.minecraft.core.NonNullList; import net.minecraft.world.Container; import net.minecraft.world.ContainerHelper; -import net.minecraft.world.ContainerListener; +import io.wispforest.accessories.utils.ContainerListener; import net.minecraft.world.ItemStackWithSlot; import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.StackedItemContents; diff --git a/common/src/main/java/io/wispforest/accessories/utils/CollectionUtils.java b/common/src/main/java/io/wispforest/accessories/utils/CollectionUtils.java index 2652d9281..4b955cb4e 100644 --- a/common/src/main/java/io/wispforest/accessories/utils/CollectionUtils.java +++ b/common/src/main/java/io/wispforest/accessories/utils/CollectionUtils.java @@ -1,20 +1,26 @@ package io.wispforest.accessories.utils; import it.unimi.dsi.fastutil.Hash; +import org.apache.commons.lang3.mutable.MutableInt; import java.util.LinkedHashMap; import java.util.Map; import java.util.function.Function; import java.util.stream.Collector; import java.util.stream.Collectors; +import java.util.stream.Stream; public class CollectionUtils { - public static Collector, ?, LinkedHashMap> toLinkedMap() { + public static Collector, ?, LinkedHashMap> linkedMapCollector() { return Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (obj1, obj2) -> obj1, LinkedHashMap::new); } - public static Collector> toLinkedMap(Function keyMapper) { - return Collectors.toMap(keyMapper, t -> t, (obj1, obj2) -> obj1, LinkedHashMap::new); + public static Collector> linkedMapKeyCollector(Function keyMapper) { + return Collectors.toMap(keyMapper, Function.identity(), (obj1, obj2) -> obj1, LinkedHashMap::new); + } + + public static Collector> linkedMapValueCollector(Function valueMapper) { + return Collectors.toMap(Function.identity(), valueMapper, (obj1, obj2) -> obj1, LinkedHashMap::new); } private static final Hash.Strategy IDENTITY_STRATEGY = new Hash.Strategy() { @@ -32,4 +38,29 @@ public boolean equals(Object a, Object b) { public static Hash.Strategy identityHash() { return (Hash.Strategy) IDENTITY_STRATEGY; } + + public static Stream mapWithIndex(Stream stream, IndexMapper mapper) { + var index = new MutableInt(0); + + if (stream.isParallel()) { + throw new IllegalStateException("Unable to mapWithIndex on parallel map due to the unordered nature of operation!"); + } + + return stream.map(t -> mapper.map(index.getAndAdd(1), t)); + } + + public static Stream flatMapWithIndex(Stream stream, IndexMapper> mapper) { + var index = new MutableInt(0); + + if (stream.isParallel()) { + throw new IllegalStateException("Unable to mapWithIndex on parallel map due to the unordered nature of operation!"); + } + + return stream.flatMap(t -> mapper.map(index.getAndAdd(1), t)); + } + + + public interface IndexMapper { + R map(int index, T t); + } } diff --git a/common/src/main/java/io/wispforest/accessories/utils/ComponentOps.java b/common/src/main/java/io/wispforest/accessories/utils/ComponentOps.java new file mode 100644 index 000000000..2e9fcfeb7 --- /dev/null +++ b/common/src/main/java/io/wispforest/accessories/utils/ComponentOps.java @@ -0,0 +1,150 @@ +package io.wispforest.accessories.utils; + +import io.wispforest.accessories.Accessories; +import io.wispforest.accessories.AccessoriesClientInternals; +import io.wispforest.accessories.api.tooltip.TooltipComponentBuilder; +import io.wispforest.accessories.api.tooltip.impl.TooltipEntry; +import net.minecraft.locale.Language; +import net.minecraft.network.chat.*; +import net.minecraft.network.chat.contents.PlainTextContents; +import net.minecraft.util.FormattedCharSequence; +import net.minecraft.util.FormattedCharSink; +import io.wispforest.accessories.pond.TooltipFlagExtended; +import net.minecraft.world.item.TooltipFlag; + +import java.util.*; +import java.util.function.Function; + +public class ComponentOps { + + private static final List bitmasks = new ArrayList<>(); + + static { + var inst = AccessoriesClientInternals.getInstance(); + + bitmasks.addAll( + List.of( + inst.createBitFlag(true, false, false), + inst.createBitFlag(true, true, false), + inst.createBitFlag(true, true, true), + inst.createBitFlag(false, true, true), + inst.createBitFlag(false, false, true) + ) + ); + } + + public static ExtraInfoFooter attemptToAddExtraInfoFooter(SequencedCollection baseKeys, TooltipFlag baseFlag, Function comparisonFunc) { + var keys = new LinkedHashSet<>(baseKeys); + + for (var bitmask : bitmasks) { + var newFlag = ((TooltipFlagExtended) baseFlag).withMask(bitmask); + var hasChanged = comparisonFunc.apply(newFlag); + + if (hasChanged) { + if (((TooltipFlagExtended) newFlag).hasShiftDown() && !((TooltipFlagExtended) baseFlag).hasShiftDown()) keys.add("key.keyboard.left.shift"); + if (((TooltipFlagExtended) newFlag).hasAltDown() && !((TooltipFlagExtended) baseFlag).hasAltDown()) keys.add("key.keyboard.left.alt"); + if (((TooltipFlagExtended) newFlag).hasControlDown() && !((TooltipFlagExtended) baseFlag).hasControlDown()) keys.add("key.keyboard.left.control"); + } + + if (keys.size() >= 3) break; + } + + return new ExtraInfoFooter(keys.stream().collect(CollectionUtils.linkedMapValueCollector(Component::translatable))); + } + + public static final class ExtraInfoFooter { + private final SequencedMap keyToFormattedText; + + public ExtraInfoFooter(SequencedMap keyToFormattedText) { + this.keyToFormattedText = keyToFormattedText; + } + + public void addTo(TooltipComponentBuilder builder) { + if (keyToFormattedText.isEmpty()) return; + + builder + .add(ComponentOps.extraInfoFooter(keyToFormattedText.sequencedValues())); + } + + public ExtraInfoFooter combine(ExtraInfoFooter other) { + var map = new LinkedHashMap<>(this.keyToFormattedText); + + other.keyToFormattedText.forEach(map::putIfAbsent); + + return new ExtraInfoFooter(map); + } + + public SequencedMap keyToFormattedText() { + return Collections.unmodifiableSequencedMap(keyToFormattedText); + } + } + + public static Component extraInfoFooter(SequencedCollection keys) { + if (keys.isEmpty()) return Component.empty(); + + return Accessories.translationWithArgs("tooltip.extra_info") + .withArgs(fromEntriesAnyList(keys, "extra_info.list", Function.identity(), (startingEntries, lastEntry) -> { + return Accessories.translationWithArgs("tooltip.extra_info.2_or_more") + .withArgs(startingEntries, lastEntry); + })); + } + + public static FormattedCharSequence getVisualOrderText(FormattedText text) { + return (text instanceof Component component) + ? component.getVisualOrderText() + : Language.getInstance().getVisualOrder(text); + } + + + public static int getHashCode(FormattedText text) { + var hasher = new HashingCharSink(); + ComponentOps.getVisualOrderText(text).accept(hasher); + return hasher.hash; + } + + private static class HashingCharSink implements FormattedCharSink { + private int hash = 0; + + @Override + public boolean accept(int charIndex, Style style, int codePoint) { + hash = Objects.hash(hash, charIndex + Character.charCount(codePoint), style); + + return true; + } + } + + public interface AnyTextBuilder { + MutableComponent build(Component startingEntries, Component lastEntry); + } + + public static boolean isEmpty(Component component) { + return component.getContents() == PlainTextContents.EMPTY; + } + + public static Component validateComponent(Component component, String type) { + if (Accessories.DEBUG) { + Objects.requireNonNull(component, type + " requires non null reason Component!"); + + if (isEmpty(component)) throw new IllegalStateException(type + " requires non empty reason Component!"); + } + + return component; + } + + public static MutableComponent fromEntriesAnyList(SequencedCollection entries, String entryKeyPart, Function func, AnyTextBuilder builder) { + if (entries.isEmpty()) return Component.empty(); + if (entries.size() == 1) return func.apply(entries.getFirst()); + + var list = (entries instanceof List list1 ? list1 : new ArrayList<>(entries)) + .subList(0, entries.size() - 1); + + return builder.build(ComponentUtils.formatList(list, Accessories.translation("tooltip." + entryKeyPart + ".entry_separator"), func::apply), func.apply(entries.getLast())); + } + + public static MutableComponent fromEntriesDivided(SequencedCollection entries, String entryKeyPart, Function func) { + if (entries.isEmpty()) return Component.empty(); + if (entries.size() == 1) return func.apply(entries.getFirst()); + + return ComponentUtils.formatList(entries, Accessories.translation("tooltip." + entryKeyPart + ".entry_separator"), func::apply); + } +} diff --git a/common/src/main/java/io/wispforest/accessories/utils/ContainerListener.java b/common/src/main/java/io/wispforest/accessories/utils/ContainerListener.java new file mode 100644 index 000000000..a399597c3 --- /dev/null +++ b/common/src/main/java/io/wispforest/accessories/utils/ContainerListener.java @@ -0,0 +1,8 @@ +package io.wispforest.accessories.utils; + +import net.minecraft.world.Container; + +@FunctionalInterface +public interface ContainerListener { + void containerChanged(Container container); +} diff --git a/common/src/main/java/io/wispforest/accessories/utils/EndecUtils.java b/common/src/main/java/io/wispforest/accessories/utils/EndecUtils.java index 569a2d2b7..4757493ba 100644 --- a/common/src/main/java/io/wispforest/accessories/utils/EndecUtils.java +++ b/common/src/main/java/io/wispforest/accessories/utils/EndecUtils.java @@ -16,7 +16,7 @@ import io.wispforest.endec.impl.StructField; import io.wispforest.endec.util.MapCarrierDecodable; import io.wispforest.endec.util.MapCarrierEncodable; -import io.wispforest.owo.mixin.serialization.ForwardingDynamicOpsAccessor; +import io.wispforest.owo.mixin.serialization.DelegatingOpsAccessor; import io.wispforest.owo.mixin.serialization.RegistryOpsAccessor; import io.wispforest.owo.serialization.CodecUtils; import io.wispforest.owo.serialization.RegistriesAttribute; @@ -24,7 +24,7 @@ import io.wispforest.owo.serialization.format.nbt.NbtEndec; import it.unimi.dsi.fastutil.Pair; import it.unimi.dsi.fastutil.floats.FloatArrayList; -import net.minecraft.Util; +import net.minecraft.util.Util; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.EndTag; @@ -95,9 +95,9 @@ public static StructEndec blockStateEndec(String typeKey) { block -> { BlockState stateHolder = block.defaultBlockState(); - if (stateHolder.getValues().isEmpty()) return MapCodec.unit(stateHolder); + if (stateHolder.getValues().findAny().isEmpty()) return MapCodec.unit(stateHolder); - return (((StateHolderAccessor) stateHolder).accessories$propertiesCodec()) + return block.getStateDefinition().propertiesCodec() .codec() .lenientOptionalFieldOf("properties") .xmap(optional -> optional.orElse(stateHolder), Optional::of); @@ -367,7 +367,7 @@ private static SerializationContext createContext(DynamicOps ops, Serializati : null; while (rootOps instanceof DelegatingOps) { - rootOps = ((ForwardingDynamicOpsAccessor) rootOps).owo$delegate(); + rootOps = ((DelegatingOpsAccessor) rootOps).owo$delegate(); if (context == null && rootOps instanceof ContextHolder holder) { context = holder.capturedContext().and(assumedContext); diff --git a/common/src/main/java/io/wispforest/accessories/utils/JsonUtils.java b/common/src/main/java/io/wispforest/accessories/utils/JsonUtils.java index f20f539f7..c7beddbc6 100644 --- a/common/src/main/java/io/wispforest/accessories/utils/JsonUtils.java +++ b/common/src/main/java/io/wispforest/accessories/utils/JsonUtils.java @@ -3,7 +3,7 @@ import com.google.gson.*; import com.mojang.logging.LogUtils; import net.minecraft.resources.FileToIdConverter; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.server.packs.resources.Resource; import net.minecraft.server.packs.resources.ResourceManager; import net.minecraft.util.GsonHelper; @@ -21,10 +21,10 @@ public class JsonUtils { private static final Logger LOGGER = LogUtils.getLogger(); - public record FileResourceData(ResourceLocation fileLocation, JsonObject obj, Resource resource){} + public record FileResourceData(Identifier fileLocation, JsonObject obj, Resource resource){} - public static Map scanDirectoryWithReplace(ResourceManager resourceManager, FileToIdConverter fileToIdConverter) { - var outputResources = new LinkedHashMap(); + public static Map scanDirectoryWithReplace(ResourceManager resourceManager, FileToIdConverter fileToIdConverter) { + var outputResources = new LinkedHashMap(); for(var entry : fileToIdConverter.listMatchingResourceStacks(resourceManager).entrySet()) { var filePath = entry.getKey(); diff --git a/common/src/main/resources/accessories-common.mixins.json b/common/src/main/resources/accessories-common.mixins.json index 487f68618..3e7724d39 100644 --- a/common/src/main/resources/accessories-common.mixins.json +++ b/common/src/main/resources/accessories-common.mixins.json @@ -19,6 +19,7 @@ "client.DefaultTooltipPositionerMixin", "client.EntityRendererMixin", "client.EquipmentLayerRendererAccessor", + "client.GuiGraphicsAccessor", "client.GuiGraphicsMixin", "client.GuiGraphicsMixin$ScissorStackMixin", "client.HumanoidArmorLayerAccessor", @@ -30,7 +31,6 @@ "client.LocalPlayerMixin", "client.MinecraftMixin", "client.ModelPartAccessor", - "client.RenderPhaseMixin", "client.RenderTargetMixin", "client.WingsLayerMixin", "client.cosmetic.LivingEntityMixin", @@ -52,6 +52,7 @@ "DataPackContentsMixin", "DefaultDispenseItemBehaviorAccessor", "DispenserBlockMixin", + "EnchantCommandAccessor", "EnchantedCountIncreaseFunctionMixin", "EnchantedItemInUseMixin", "EnchantmentAttributeEffectMixin", @@ -77,8 +78,6 @@ "SimpleJsonResourceReloadListenerAccessor", "SimpleJsonResourceReloadListenerMixin", "StateHolderAccessor", - "GameRulesAccessor", - "GameRulesAccessor$BooleanValueAccessor", "owo.ConfigWrapperAccessor", "owo.DumpdataCommandMixin", "owo.NbtDeserializerMixin", diff --git a/common/src/main/resources/accessories.accesswidener b/common/src/main/resources/accessories.accesswidener index 41ce77808..51d51ba85 100644 --- a/common/src/main/resources/accessories.accesswidener +++ b/common/src/main/resources/accessories.accesswidener @@ -1,4 +1,4 @@ -accessWidener v2 named +accessWidener v2 official accessible class net/minecraft/resources/RegistryOps$HolderLookupAdapter extendable class net/minecraft/resources/RegistryOps$HolderLookupAdapter @@ -9,12 +9,12 @@ extendable class net/minecraft/world/item/enchantment/EnchantmentHelper$Enchantm accessible class net/minecraft/world/inventory/ArmorSlot extendable class net/minecraft/world/inventory/ArmorSlot -extendable method net/minecraft/client/gui/screens/inventory/AbstractContainerScreen renderSlotHighlightBack (Lnet/minecraft/client/gui/GuiGraphics;)V -extendable method net/minecraft/client/gui/screens/inventory/AbstractContainerScreen renderSlotHighlightFront (Lnet/minecraft/client/gui/GuiGraphics;)V -extendable method net/minecraft/client/gui/screens/inventory/AbstractContainerScreen renderFloatingItem (Lnet/minecraft/client/gui/GuiGraphics;Lnet/minecraft/world/item/ItemStack;IILjava/lang/String;)V +accessible method net/minecraft/client/gui/screens/inventory/AbstractContainerScreen extractSlotHighlightBack (Lnet/minecraft/client/gui/GuiGraphicsExtractor;)V +accessible method net/minecraft/client/gui/screens/inventory/AbstractContainerScreen extractSlotHighlightFront (Lnet/minecraft/client/gui/GuiGraphicsExtractor;)V +accessible method net/minecraft/client/gui/screens/inventory/AbstractContainerScreen extractFloatingItem (Lnet/minecraft/client/gui/GuiGraphicsExtractor;Lnet/minecraft/world/item/ItemStack;IILjava/lang/String;)V accessible class net/minecraft/server/level/ChunkMap$TrackedEntity accessible method net/minecraft/world/entity/player/Player closeContainer ()V accessible class net/minecraft/client/gui/screens/MenuScreens$ScreenConstructor -accessible field net/minecraft/client/gui/GuiGraphics guiRenderState Lnet/minecraft/client/gui/render/state/GuiRenderState; -accessible field net/minecraft/client/gui/GuiGraphics scissorStack Lnet/minecraft/client/gui/GuiGraphics$ScissorStack; \ No newline at end of file +accessible field net/minecraft/client/gui/GuiGraphicsExtractor guiRenderState Lnet/minecraft/client/renderer/state/gui/GuiRenderState; +accessible field net/minecraft/client/gui/GuiGraphicsExtractor scissorStack Lnet/minecraft/client/gui/GuiGraphicsExtractor$ScissorStack; \ No newline at end of file diff --git a/common/src/main/resources/architectury.common.json b/common/src/main/resources/architectury.common.json index efec04e55..fafdb5e84 100644 --- a/common/src/main/resources/architectury.common.json +++ b/common/src/main/resources/architectury.common.json @@ -11,7 +11,7 @@ "io/wispforest/accessories/pond/AccessoriesRenderStateAPI" ], "net/minecraft/class_1836": [ - "io/wispforest/accessories/pond/TooltipFlagExtension" + "io/wispforest/accessories/pond/TooltipFlagExtended" ] } } \ No newline at end of file diff --git a/common/src/main/resources/assets/accessories/font/one_space.json b/common/src/main/resources/assets/accessories/font/one_space.json new file mode 100644 index 000000000..b98cee592 --- /dev/null +++ b/common/src/main/resources/assets/accessories/font/one_space.json @@ -0,0 +1,10 @@ +{ + "providers": [ + { + "type": "space", + "advances": { + " ": 1 + } + } + ] +} diff --git a/common/src/main/resources/assets/accessories/lang/en_us.json b/common/src/main/resources/assets/accessories/lang/en_us.json index f27992deb..54ef25e8a 100644 --- a/common/src/main/resources/assets/accessories/lang/en_us.json +++ b/common/src/main/resources/assets/accessories/lang/en_us.json @@ -1,17 +1,75 @@ { "accessories.slot.tooltip.singular": "Slot: ", "accessories.slot.tooltip.plural": "Slots: ", - "accessories.cosmetic_slot.tooltip.singular": "Cosmetic Slot: ", "accessories.cosmetic_slot.tooltip.plural": "Cosmetic Slots: ", - "accessories.slot.any": "Any", "accessories.slot.except": " except ", - "accessories.tooltip.attributes.any": "When Equipped:", "accessories.tooltip.attributes.slot": "When Equipped in %s:", "accessories.tooltip.currently_equipped_in": "Equipped in: ", + "accessories.tooltip.equipment_reasoning": "Equipment Reasoning: ", + "accessories.tooltip.accessory_reasoning": "Accessory Reasoning: ", + + "accessories.tooltip.slot.invalid": "%s", + "accessories.tooltip.slot.valid": "%s", + "accessories.tooltip.slot.irrelevant": "%s", + + "accessories.tooltip.extra_info": "Hold %s to show more info. ", + "accessories.tooltip.extra_info.list.entry_separator": ", ", + "accessories.tooltip.extra_info.2_or_more": "%s or %s", + + "accessories.tooltip.equipment_reasoning.list_entry.invalid": "(❌): ", + "accessories.tooltip.equipment_reasoning.list_entry.valid": "(✔): ", + "accessories.tooltip.equipment_reasoning.list_entry.irrelevant": "(#): ", + + "accessories.tooltip.equipment_reasoning.indent_entry": " ", + + "accessories.tooltip.list_entry": " ‐ ", + "accessories.tooltip.indent_entry": " ", + + "accessories.tooltip.validator.simplied_message.valid": "Can be equipped into the slot.", + "accessories.tooltip.validator.simplied_message.invalid": "Can not be equipped into the slot.", + "accessories.tooltip.validator.simplied_message.irrelevant": "Such is irrelevant for the given slot.", + + "accessories.tooltip.validator.always_valid": "Anything can fit within this slot!.", + "accessories.tooltip.validator.always_invalid": "The slot is unable to take any Accessory, forever!", + + "accessories.tooltip.validator.tag.simple.valid": "Valid for the given group(s).", + "accessories.tooltip.validator.tag.simple.invalid": "Invalid for the given group(s).", + + "accessories.tooltip.validator.tag.entry_separator": ", ", + + "accessories.tooltip.validator.tag.advanced.valid.any": "Entry is within one of the group(s): %s", + "accessories.tooltip.validator.tag.advanced.valid.all": "Entry is within all of group(s): %s", + "accessories.tooltip.validator.tag.advanced.invalid.any": "Entry isn't within any of the group(s): %s", + "accessories.tooltip.validator.tag.advanced.invalid.all": "Entry isn't within all of group(s): %s", + + "accessories.tooltip.validator.set.entry_separator": ", ", + + "accessories.tooltip.validator.set.simple.valid": "Valid for the given %s group.", + "accessories.tooltip.validator.set.simple.invalid": "Invalid for the given %s group.", + + "accessories.tooltip.validator.set.advanced.valid": "Entry is one of the valid %s: %s", + "accessories.tooltip.validator.set.advanced.invalid": "Entry isn't any of the valid %s: %s", + + "minecraft.entity_type.singular": "Entity", + "minecraft.entity_type.plural": "Entities", + + "accessories.tooltip.validator.cursed": "Its bound to you till death!", + + "accessories.tooltip.validator.attribute.simple.include": "Contains attributes for the given slot.", + "accessories.tooltip.validator.attribute.simple.excludes": "Contains no attributes for the given slot.", + + "accessories.tooltip.validator.component.entry_separator": ", ", + + "accessories.tooltip.validator.component.advanced.invalid": "Invalid as its explicitly disallowed: %s", + "accessories.tooltip.validator.component.advanced.valid": "Valid as its explicitly allowed: %s", + "accessories.tooltip.validator.component.advanced.irrelevant": "Irrelevant as its not explicitly allowed: %s", + + "accessories.tooltip.validator.component.simple.irrelevant": "Irrelevant as its not explicitly allowed.", + "accessories.slot.hat": "Hat", "accessories.slot.face": "Face", "accessories.slot.cape": "Cape", @@ -24,12 +82,30 @@ "accessories.slot.anklet": "Anklet", "accessories.slot.shoes": "Shoes", "accessories.slot.charm": "Charm", + + "tag.item.accessories.hat": "Hat", + "tag.item.accessories.face": "Face", + "tag.item.accessories.cape": "Cape", + "tag.item.accessories.necklace": "Necklace", + "tag.item.accessories.back": "Back", + "tag.item.accessories.hand": "Hand", + "tag.item.accessories.ring": "Ring", + "tag.item.accessories.wrist": "Wrist", + "tag.item.accessories.belt": "Belt", + "tag.item.accessories.anklet": "Anklet", + "tag.item.accessories.shoes": "Shoes", + "tag.item.accessories.charm": "Charm", + "tag.item.accessories.any": "Any", + "accessories.slot.accessories.head": "Head", "accessories.slot.accessories.chest": "Chest", "accessories.slot.accessories.legs": "Legs", "accessories.slot.accessories.feet": "Feet", "accessories.slot.accessories.animal_body": "Body", - + "accessories.slot.accessories_cosmetics.head": "Head (Cosmetic)", + "accessories.slot.accessories_cosmetics.chest": "Chest (Cosmetic)", + "accessories.slot.accessories_cosmetics.legs": "Legs (Cosmetic)", + "accessories.slot.accessories_cosmetics.feet": "Feet (Cosmetic)", "accessories.slot_group.misc": "Misc", "accessories.slot_group.head": "Head", "accessories.slot_group.chest": "Chest", @@ -37,509 +113,222 @@ "accessories.slot_group.leg": "Legs", "accessories.slot_group.feet": "Feet", "accessories.slot_group.unsorted": "Unsorted", - "key.category.accessories.main": "Accessories", "accessories.key.open_accessories_screen": "Open Accessories Screen", + "accessories.key.open_others_accessories_screen": "Open Another's Accessories Screen", "accessories.commands.attribute.failed.modifier_already_present_itemstack": "Modifier %s is already present on attribute %s for stack %s", - "accessories.commands.attribute.failed.no_modifier_itemstack": "Attribute %s for stack %s has no modifier %s", "accessories.commands.attribute.modifier.add.success_itemstack": "Added modifier %s to attribute %s for stack %s", "accessories.commands.attribute.modifier.remove.success_itemstack": "Removed modifier %s from attribute %s for stack %s", "accessories.commands.attribute.modifier.value.get.success_itemstack": "Value of modifier %s on attribute %s for stack %s is %s", "accessories.commands.attribute.value.get.success": "Value of attribute %s for entity %s is %s", "accessories.commands.slot.value.get.success": "Value of slot %s for entity %s is %s", - "accessories.commands.slot.modifier.clear.all.success": "Slot Attributes for all containers has been removed for entity %s", - "accessories.commands.slot.modifier.clear.container.success": "Slot Attributes for %s has been removed for entity %s", - "accessories.argument.livingEntities.nonLiving": "Only living entities may be affected by this command, but the provided selector includes non living entities", - - "accessories.commands.feature.toggle.failure" : "'%s' dose not match any of the toggleable features: %s", - - "accessories.commands.feature.toggle.on" : "'%s' has been enabled!", - "accessories.commands.feature.toggle.off" : "'%s' has been disabled!", - - "accessories.commands.dump.failure" : "'%s' dose not match any of the valid types for logging: %s", - "accessories.commands.dump.success" : "'%s' data has been dumped to the log file!", - - "accessories.commands.slot.modifier.addition" : "Attribute '%s' has been added to slot `%s` for '%s'", - - "accessories.commands.slot.modifier.removed.failure" : "Attribute '%s' for slot '%s' was not found for '%s'!", - "accessories.commands.slot.modifier.removed.success" : "Attribute '%s' was removed for slot '%s' from '%s'!", - - "accessories.commands.nest.addition" : "Added the inputted item to the main hand stack!", - - "accessories.commands.slot.validation.added.valid" : "'%s' was added as a valid slot", - "accessories.commands.slot.validation.added.invalid" : "'%s' was added as a invalid slot", - "accessories.commands.slot.validation.removed.valid" : "'%s' was removed as a valid slot", - "accessories.commands.slot.validation.removed.invalid" : "'%s' was removed as a invalid slot", - + "accessories.commands.feature.toggle.failure": "'%s' dose not match any of the toggleable features: %s", + "accessories.commands.feature.toggle.on": "'%s' has been enabled!", + "accessories.commands.feature.toggle.off": "'%s' has been disabled!", + "accessories.commands.dump.failure": "'%s' dose not match any of the valid types for logging: %s", + "accessories.commands.dump.success": "'%s' data has been dumped to the log file!", + "accessories.commands.slot.modifier.addition": "Attribute '%s' has been added to slot `%s` for '%s'", + "accessories.commands.slot.modifier.removed.failure": "Attribute '%s' for slot '%s' was not found for '%s'!", + "accessories.commands.slot.modifier.removed.success": "Attribute '%s' was removed for slot '%s' from '%s'!", + "accessories.commands.nest.addition": "Added the inputted item to the main hand stack!", + "accessories.commands.slot.validation.added.valid": "'%s' was added as a valid slot", + "accessories.commands.slot.validation.added.invalid": "'%s' was added as a invalid slot", + "accessories.commands.slot.validation.removed.valid": "'%s' was removed as a valid slot", + "accessories.commands.slot.validation.removed.invalid": "'%s' was removed as a invalid slot", "gamerule.accessories.keepAccessoryInventory": "Keep Accessory Inventory", - - "#comment": "GUI Related Below", - + "#comment": "Config Related Below", "accessories.slot.cosmetics.toggle.show": "Show Cosmetic Slots", "accessories.slot.cosmetics.toggle.hide": "Hide Cosmetic Slots", - "accessories.display.toggle.show": "Show Accessory", "accessories.display.toggle.hide": "Hide Accessory", - "accessories.lines.toggle.show": "Show All Lines", "accessories.lines.toggle.hide": "Hide All Lines", - "accessories.unused_slots.toggle.show": "Show Unused Slots", "accessories.unused_slots.toggle.hide": "Hide Unused Slots", - "accessories.slot_cosmetics.toggle.enabled": "Show Accessories Slots", "accessories.slot_cosmetics.toggle.disabled": "Show Cosmetic Slots", - "accessories.advanced_options.toggle.enabled.tooltip": "Hide Screen options", "accessories.advanced_options.toggle.disabled.tooltip": "Show Screen options", - "accessories.unused_slots.label": "Show unused slots:", - "accessories.unused_slots.toggle.enabled": [ - "", - {"text": "[", "color": "gray"}, - {"text": "✔", "color": "#28FFBF"}, - {"text": "]", "color": "gray"}, - " Shown" - ], - "accessories.unused_slots.toggle.disabled": [ - "", - {"text": "[", "color": "gray"}, - {"text": "❌", "color": "#EB1D36"}, - {"text": "]", "color": "gray"}, - " Hidden" - ], + "accessories.unused_slots.toggle.enabled": "[✔] Shown", + "accessories.unused_slots.toggle.disabled": "[❌] Hidden", "accessories.unused_slots.toggle.enabled.tooltip": "Hide all Unused Slots", "accessories.unused_slots.toggle.disabled.tooltip": "Show all Unused Slots", - "accessories.column_amount.label": "Accessory Column Amount:", "accessories.column_amount.tooltip": "Adjusts the amount of columns for the Accessory Module", - "accessories.side_by_side_slots.label": "Cosmetic Slot Viewing Mode:", - "accessories.side_by_side_slots.toggle.enabled": [ - "", - {"text": "[", "color": "gray"}, - {"text": "O", "color": "#eab676"}, - {"text": "]", "color": "gray"}, - " Toggle" - ], - "accessories.side_by_side_slots.toggle.disabled": [ - "", - {"text": "[", "color": "gray"}, - {"text": "/", "color": "#1e81b0"}, - {"text": "]", "color": "gray"}, - " Switch" - ], + "accessories.side_by_side_slots.toggle.enabled": "[O] Toggle", + "accessories.side_by_side_slots.toggle.disabled": "[/] Switch", "accessories.side_by_side_slots.toggle.enabled.tooltip": "Switch to toggle between slots", "accessories.side_by_side_slots.toggle.disabled.tooltip": "Switch to showing or hiding Cosmetic slots", - "accessories.side_by_side_entity.label": "Amount of Entity Views:", - "accessories.side_by_side_entity.toggle.enabled": [ - "", - {"text": "[", "color": "gray"}, - {"text": "||", "color": "#32a852"}, - {"text": "]", "color": "gray"}, - " Double" - ], - "accessories.side_by_side_entity.toggle.disabled": [ - "", - {"text": "[", "color": "gray"}, - {"text": "|", "color": "#32a852"}, - {"text": "]", "color": "gray"}, - " Single" - ], + "accessories.side_by_side_entity.toggle.enabled": "[||] Double", + "accessories.side_by_side_entity.toggle.disabled": "[|] Single", "accessories.side_by_side_entity.toggle.enabled.tooltip": "Switch to toggle single entity view", "accessories.side_by_side_entity.toggle.disabled.tooltip": "Switch to toggle double entity view", - "accessories.entity_centered.label": "Entity panel centering:", - "accessories.entity_centered.toggle.enabled": [ - "", - {"text": "[", "color": "gray"}, - {"text": "✔", "color": "#28FFBF"}, - {"text": "]", "color": "gray"}, - " Enabled" - ], - "accessories.entity_centered.toggle.disabled": [ - "", - {"text": "[", "color": "gray"}, - {"text": "❌", "color": "#EB1D36"}, - {"text": "]", "color": "gray"}, - " Disabled" - ], + "accessories.entity_centered.toggle.enabled": "[✔] Enabled", + "accessories.entity_centered.toggle.disabled": "[❌] Disabled", "accessories.entity_centered.toggle.enabled.tooltip": "Allow entity to be offset from the center", "accessories.entity_centered.toggle.disabled.tooltip": "Make entity ALWAYS be close or in the center of the screen", - "accessories.widget_type.label": "Accessory widget variant:", - "accessories.widget_type.paginated": [ - "", - {"text": "[", "color": "gray"}, - {"text": "☰", "color": "#347ecf"}, - {"text": "]", "color": "gray"}, - " Paginated" - ], - "accessories.widget_type.scrollable": [ - "", - {"text": "[", "color": "gray"}, - {"text": "⏷", "color": "#953abd"}, - {"text": "]", "color": "gray"}, - " Scrollable" - ], + "accessories.widget_type.paginated": "[☰] Paginated", + "accessories.widget_type.scrollable": "[⏷] Scrollable", "accessories.widget_type.paginated.tooltip": "Uses Pages for navigating the Accessories Slots", "accessories.widget_type.scrollable.tooltip": "Uses Scrolling for navigating the Accessories Slots", - "accessories.main_widget_position.label": "Accessories widget position:", - "accessories.main_widget_position.toggle.enabled": [ - "", - {"text": "[", "color": "gray"}, - {"text": "←", "color": "#32a852"}, - {"text": "]", "color": "gray"}, - " Left" - ], - "accessories.main_widget_position.toggle.disabled": [ - "", - {"text": "[", "color": "gray"}, - {"text": "→", "color": "#32a852"}, - {"text": "]", "color": "gray"}, - " Right" - ], + "accessories.main_widget_position.toggle.enabled": "[←] Left", + "accessories.main_widget_position.toggle.disabled": "[→] Right", "accessories.main_widget_position.toggle.enabled.tooltip": "Move Accessories Widget to the Right", "accessories.main_widget_position.toggle.disabled.tooltip": "Move Accessories Widget to the Left", - "accessories.group_filter.label": "Group filter widget:", - "accessories.group_filter.toggle.enabled": [ - "", - {"text": "[", "color": "gray"}, - {"text": "✔", "color": "#28FFBF"}, - {"text": "]", "color": "gray"}, - " Shown" - ], - "accessories.group_filter.toggle.disabled": [ - "", - {"text": "[", "color": "gray"}, - {"text": "❌", "color": "#EB1D36"}, - {"text": "]", "color": "gray"}, - " Hidden" - ], + "accessories.group_filter.toggle.enabled": "[✔] Shown", + "accessories.group_filter.toggle.disabled": "[❌] Hidden", "accessories.group_filter.toggle.enabled.tooltip": "Hide group filter widget", "accessories.group_filter.toggle.disabled.tooltip": "Show group filter widget", - "accessories.side_widget_position.label": "Side widget position:", - "accessories.side_widget_position.toggle.enabled": [ - "", - {"text": "[", "color": "gray"}, - {"text": "()", "color": "#32a852"}, - {"text": "]", "color": "gray"}, - " Together" - ], - "accessories.side_widget_position.toggle.disabled": [ - "", - {"text": "[", "color": "gray"}, - {"text": "||", "color": "#32a852"}, - {"text": "]", "color": "gray"}, - " Separate" - ], + "accessories.side_widget_position.toggle.enabled": "[()] Together", + "accessories.side_widget_position.toggle.disabled": "[||] Separate", "accessories.side_widget_position.toggle.enabled.tooltip": "Move Side Widget to be with the Accessories Widget", "accessories.side_widget_position.toggle.disabled.tooltip": "Move Side widget to be opposite to Accessories Widget", - "accessories.dark_mode_toggle.label": "Screen theme mode:", - "accessories.dark_mode_toggle.toggle.enabled": [ - "", - {"text": "[", "color": "gray"}, - {"text": "☽", "color": "#3d29c2"}, - {"text": "]", "color": "gray"}, - " Dark" - ], - "accessories.dark_mode_toggle.toggle.disabled": [ - "", - {"text": "[", "color": "gray"}, - {"text": "☀", "color": "#bffa9b"}, - {"text": "]", "color": "gray"}, - " Light" - ], + "accessories.dark_mode_toggle.toggle.enabled": "[☽] Dark", + "accessories.dark_mode_toggle.toggle.disabled": "[☀] Light", "accessories.dark_mode_toggle.toggle.enabled.tooltip": "Change theme to Light Mode", "accessories.dark_mode_toggle.toggle.disabled.tooltip": "Change theme to Dark Mode", - "accessories.show_equipped_stack_slot_type.label": "Show equipped Type:", - "accessories.show_equipped_stack_slot_type.toggle.enabled": [ - "", - {"text": "[", "color": "gray"}, - {"text": "✔", "color": "#28FFBF"}, - {"text": "]", "color": "gray"}, - " Shown" - ], - "accessories.show_equipped_stack_slot_type.toggle.disabled": [ - "", - {"text": "[", "color": "gray"}, - {"text": "❌", "color": "#EB1D36"}, - {"text": "]", "color": "gray"}, - " Hidden" - ], + "accessories.show_equipped_stack_slot_type.toggle.enabled": "[✔] Shown", + "accessories.show_equipped_stack_slot_type.toggle.disabled": "[❌] Hidden", "accessories.show_equipped_stack_slot_type.toggle.enabled.tooltip": "Hide equipped stack Slot type", "accessories.show_equipped_stack_slot_type.toggle.disabled.tooltip": "Show equipped stack Slot type", - "accessories.entity_look_at_cursor.label": "Entity looks at Mouse:", - "accessories.entity_look_at_cursor.toggle.enabled": [ - "", - {"text": "[", "color": "gray"}, - {"text": "✔", "color": "#28FFBF"}, - {"text": "]", "color": "gray"}, - " Enabled" - ], - "accessories.entity_look_at_cursor.toggle.disabled": [ - "", - {"text": "[", "color": "gray"}, - {"text": "❌", "color": "#EB1D36"}, - {"text": "]", "color": "gray"}, - " Disabled" - ], + "accessories.entity_look_at_cursor.toggle.enabled": "[✔] Enabled", + "accessories.entity_look_at_cursor.toggle.disabled": "[❌] Disabled", "accessories.entity_look_at_cursor.toggle.enabled.tooltip": "Disable looking at cursor", "accessories.entity_look_at_cursor.toggle.disabled.tooltip": "Enable looking at cursor", - "accessories.crafting_grid.toggle.enabled.tooltip": "Hide crafting grid", "accessories.crafting_grid.toggle.disabled.tooltip": "Show crafting grid", - - "accessories.selection_screen.message": [ - "Below is a set of screen options that you \n", - "can choose from depending on the style of \n", - "Modpack or your play style. \n\n", - "Do note that you can change such within the \n", - "Accessories Config if the given option is not \n", - "to your liking." - ], - + "accessories.selection_screen.message": "Below is a set of screen options that you \ncan choose from depending on the style of \nModpack or your play style. \n\nDo note that you can change such within the \nAccessories Config if the given option is not \nto your liking.", "accessories.back.screen": "To Previous Screen", "accessories.open.screen": "Open Accessories Screen", - "accessories.reset.group_filter": "Reset Group Filters", - - "#comment": "Config Related Below", - "text.config.accessories.title": "Accessories Config", - "text.config.accessories.option.useExperimentalCaching": "Use Experimental Caching", - "text.config.accessories.option.useExperimentalCaching.tooltip": [ - "Attempts to cache various ItemStack lookups\n", - "to be more performant but may cause issues." - ], - + "text.config.accessories.option.useExperimentalCaching.tooltip": "Attempts to cache various ItemStack lookups\nto be more performant but may cause issues.", "text.config.accessories.category.contentOptions": "Content Options", - "text.config.accessories.category.contentOptions.tooltip": [ - "Contains more content focused options like glider and totem equippablity" - ], - + "text.config.accessories.category.contentOptions.tooltip": "Contains more content focused options like glider and totem equippablity", "text.config.accessories.option.contentOptions.validGliderSlots": "Valid Glider Slots", - "text.config.accessories.option.contentOptions.validGliderSlots.tooltip": [ - "Adds the slots to which a Glider item is allowed to be equipped." - ], - + "text.config.accessories.option.contentOptions.validGliderSlots.tooltip": "Adds the slots to which a Glider item is allowed to be equipped.", "text.config.accessories.option.contentOptions.allowGliderEquip": "Allow Gliders to be Equip", - "text.config.accessories.option.contentOptions.allowGliderEquip.tooltip": [ - "Toggles the ability for Gliders to be equipped within Accessories Slots." - ], - + "text.config.accessories.option.contentOptions.allowGliderEquip.tooltip": "Toggles the ability for Gliders to be equipped within Accessories Slots.", "text.config.accessories.option.contentOptions.validTotemSlots": "Valid Totem Slots", - "text.config.accessories.option.contentOptions.validTotemSlots.tooltip": [ - "Adds the slots to which a Totem item is allowed to be equipped." - ], - + "text.config.accessories.option.contentOptions.validTotemSlots.tooltip": "Adds the slots to which a Totem item is allowed to be equipped.", "text.config.accessories.option.contentOptions.allowTotemEquip": "Allow Totems to be Equip", - "text.config.accessories.option.contentOptions.allowTotemEquip.tooltip": [ - "Toggles the ability for Totems to be equipped within Accessories Slots." - ], - + "text.config.accessories.option.contentOptions.allowTotemEquip.tooltip": "Toggles the ability for Totems to be equipped within Accessories Slots.", "text.config.accessories.option.contentOptions.validBannerSlots": "Valid Banner Slots", - "text.config.accessories.option.contentOptions.validBannerSlots.tooltip": [ - "Adds the slots to which a Banner item is allowed to be equipped." - ], - + "text.config.accessories.option.contentOptions.validBannerSlots.tooltip": "Adds the slots to which a Banner item is allowed to be equipped.", "text.config.accessories.option.contentOptions.allowBannerEquip": "Allow Banners to be Equip", - "text.config.accessories.option.contentOptions.allowBannerEquip.tooltip": [ - "Toggles the ability for Banners to be equipped within Accessories Slots." - ], - + "text.config.accessories.option.contentOptions.allowBannerEquip.tooltip": "Toggles the ability for Banners to be equipped within Accessories Slots.", "text.config.accessories.category.clientOptions": "Client Options", - "text.config.accessories.category.clientOptions.tooltip": [ - "Contains more generic client side options for rendering or player input" - ], - + "text.config.accessories.category.clientOptions.tooltip": "Contains more generic client side options for rendering or player input", "text.config.accessories.option.clientOptions.forceNullRenderReplacement": "Force Empty Render Replacement", - "text.config.accessories.option.clientOptions.forceNullRenderReplacement.tooltip": [ - "Forces any registered render found to be no\n", - "rendering to instead use default rendering." - ], - + "text.config.accessories.option.clientOptions.forceNullRenderReplacement.tooltip": "Forces any registered render found to be no\nrendering to instead use default rendering.", "text.config.accessories.option.clientOptions.disableEmptySlotScreenError": "Disable Empty Accessory Error", - "text.config.accessories.option.clientOptions.disableEmptySlotScreenError.tooltip": [ - "Disables the error message displayed if the accessories\n", - "screen is opened and no used slots were found." - ], - + "text.config.accessories.option.clientOptions.disableEmptySlotScreenError.tooltip": "Disables the error message displayed if the accessories\nscreen is opened and no used slots were found.", "text.config.accessories.option.clientOptions.showCosmeticAccessories": "Show Item Cosmetic Rendering", - "text.config.accessories.option.clientOptions.showCosmeticAccessories.tooltip": [ - "Enables/Disables the rendering of cosmetic item variants if equipped." - ], - + "text.config.accessories.option.clientOptions.showCosmeticAccessories.tooltip": "Enables/Disables the rendering of cosmetic item variants if equipped.", "text.config.accessories.option.clientOptions.disabledDefaultRenders": "Disabled Default Rendering", - "text.config.accessories.option.clientOptions.disabledDefaultRenders.tooltip": [ - "Disables the included default renderer rendering of items if being used." - ], - + "text.config.accessories.option.clientOptions.disabledDefaultRenders.tooltip": "Disables the included default renderer rendering of items if being used.", "text.config.accessories.option.clientOptions.equipControl": "Quick Hand Equip Mode", - "text.config.accessories.option.clientOptions.equipControl.tooltip": [ - "Changes the mode used to quickly equip a stack from your hand." - ], - + "text.config.accessories.option.clientOptions.equipControl.tooltip": "Changes the mode used to quickly equip a stack from your hand.", "text.config.accessories.enum.playerEquipControl.must_crouch": "Requires Crouch", "text.config.accessories.enum.playerEquipControl.must_not_crouch": "Without Crouch", "text.config.accessories.enum.playerEquipControl.disabled": "Disabled", - "text.config.accessories.option.screenOptions.prioritizeCreativeScreen": "Prioritize Opening Creative Screen", - "text.config.accessories.option.screenOptions.prioritizeCreativeScreen.tooltip": [ - "Will attempt to open the Creative Screen instead of the Accessories\n", - "screen while in creative mode." - ], - + "text.config.accessories.option.screenOptions.prioritizeCreativeScreen.tooltip": "Will attempt to open the Creative Screen instead of the Accessories\nscreen while in creative mode.", "text.config.accessories.category.screenOptions": "Screen Options", - "text.config.accessories.category.screenOptions.tooltip": [ - "Contains all screen configuration options for all variants and injected button offset" - ], - + "text.config.accessories.category.screenOptions.tooltip": "Contains all screen configuration options for all variants and injected button offset", "text.config.accessories.option.screenOptions.selectedScreenType": "Selected Screen Type", - "text.config.accessories.option.screenOptions.selectedScreenType.tooltip": [ - "Used to adjust what screen will be used, none will\n", - "bring a prompt for user selection." - ], - + "text.config.accessories.option.screenOptions.selectedScreenType.tooltip": "Used to adjust what screen will be used, none will\nbring a prompt for user selection.", "text.config.accessories.enum.screenType.none": "Undecided", "text.config.accessories.enum.screenType.original": "Original", "text.config.accessories.enum.screenType.experimental_v1": "Experimental", - "text.config.accessories.section.accessories_screen": "Accessory Screen Specific Options", - "text.config.accessories.option.screenOptions.defaultValues": "Global Screen Options", - "text.config.accessories.option.screenOptions.defaultValues.tooltip": [ - "Used to adjust the DEFAULT screen options like amount of columns,\n", - "the given theme, etc. Such can also be adjusted in game per user." - ], - + "text.config.accessories.option.screenOptions.defaultValues.tooltip": "Used to adjust the DEFAULT screen options like amount of columns,\nthe given theme, etc. Such can also be adjusted in game per user.", "text.config.accessories.option.screenOptions.backButtonClosesScreen": "Close screen instead of going back to previous screen", "text.config.accessories.option.screenOptions.backButtonClosesScreen.tooltip": "Attempts to close the screen instead of going back to the previous inventory screen if possible.", - "text.config.accessories.option.screenOptions.keybindIgnoresOtherTargets": "Open Screen keybind Ignores other Targets", "text.config.accessories.option.screenOptions.keybindIgnoresOtherTargets.tooltip": "Useful if you want the keybind to ignore other targets found like the animal you are riding.", - "text.config.accessories.option.screenOptions.showUnusedSlots": "Show Unused Slots", "text.config.accessories.option.screenOptions.showUnusedSlots.tooltip": "Toggles filtering of unused slots", - "text.config.accessories.option.screenOptions.allowSlotScrolling": "Allow Screen Slot Scrolling", - "text.config.accessories.option.screenOptions.allowSlotScrolling.tooltip": [ - "Useful if the given mod allows for scrolling stacks\n", - "leading to issues when going though accessories." - ], - + "text.config.accessories.option.screenOptions.allowSlotScrolling.tooltip": "Useful if the given mod allows for scrolling stacks\nleading to issues when going though accessories.", "text.config.accessories.option.screenOptions.showEquippedStackSlotType": "Show Equipped Stacks Slot Type", - "text.config.accessories.option.screenOptions.showEquippedStackSlotType.tooltip": [ - "Shows the given slot type that the given stack is equipped in within its tooltip." - ], - + "text.config.accessories.option.screenOptions.showEquippedStackSlotType.tooltip": "Shows the given slot type that the given stack is equipped in within its tooltip.", "text.config.accessories.option.screenOptions.entityLooksAtMouseCursor": "Make Entity follow the Mouse Cursor", - "text.config.accessories.option.screenOptions.entityLooksAtMouseCursor.tooltip": [ - "If enabled, makes the entity follow the mouse cursor\n", - "otherwise it allows for manual rotation of the entity." - ], - + "text.config.accessories.option.screenOptions.entityLooksAtMouseCursor.tooltip": "If enabled, makes the entity follow the mouse cursor\notherwise it allows for manual rotation of the entity.", "text.config.accessories.option.screenOptions.allowSideBarCraftingGrid": "Allow Crafting Grid within Sidebar", - "text.config.accessories.option.screenOptions.allowSideBarCraftingGrid.tooltip": [ - "If group filters are not present, it will attempt to put\n", - "the crafting grid within the sidebar instead down below." - ], - + "text.config.accessories.option.screenOptions.allowSideBarCraftingGrid.tooltip": "If group filters are not present, it will attempt to put\nthe crafting grid within the sidebar instead down below.", "text.config.accessories.section.button_offsets": "Injected Button Offsets", - "text.config.accessories.option.screenOptions.inventoryButtonOffset": "Inventory Button Offset", - "text.config.accessories.option.screenOptions.menuButtonInjections": "Injected Screen Buttons", - "text.config.accessories.option.screenOptions.menuButtonInjections.menuType": "Menu Id", "text.config.accessories.option.screenOptions.menuButtonInjections.xOffset": "X Offset", "text.config.accessories.option.screenOptions.menuButtonInjections.yOffset": "Y Offset", "text.config.accessories.option.screenOptions.menuButtonInjections.mini": "Is Mini Version", - "text.config.accessories.option.screenOptions.inventoryButtonOffset.x": "X Offset", "text.config.accessories.option.screenOptions.inventoryButtonOffset.y": "Y Offset", - "text.config.accessories.option.screenOptions.creativeInventoryButtonOffset": "Creative Inventory Button Offset", - "text.config.accessories.option.screenOptions.creativeInventoryButtonOffset.x": "X Offset", "text.config.accessories.option.screenOptions.creativeInventoryButtonOffset.y": "Y Offset", - "text.config.accessories.section.experimental": "Experimental Screen", - "text.config.accessories.option.screenOptions.isDarkMode": "Use Dark mode theme", - "text.config.accessories.option.screenOptions.isDarkMode.tooltip": [ - "Changes the theming for the experimental screen to be dark mode." - ], - + "text.config.accessories.option.screenOptions.isDarkMode.tooltip": "Changes the theming for the experimental screen to be dark mode.", "text.config.accessories.option.screenOptions.alwaysShowCraftingGrid": "Always show Crafting grid", - "text.config.accessories.option.screenOptions.alwaysShowCraftingGrid.tooltip": [ - "Will remove the toggle button for the crafting grid and always show it within the experimental screen." - ], + "text.config.accessories.option.screenOptions.alwaysShowCraftingGrid.tooltip": "Will remove the toggle button for the crafting grid and always show it within the experimental screen.", - "text.config.accessories.section.legacy": "Original Screen", + "text.config.accessories.option.screenOptions.equipCheckTooltipType": "Equipment Tooltip Checking Type", + "text.config.accessories.option.screenOptions.equipCheckTooltipType.tooltip": "Changes how much info is disabled about if a Accessory can be equipped into a given slot or be unequipped from a given slot", - "text.config.accessories.option.screenOptions.showGroupTabs": "Show quick seeking group tabs", - "text.config.accessories.option.screenOptions.showGroupTabs.tooltip": [ - "Toggles the group tabs within the original screen to be shown or hidden." - ], + "text.config.accessories.option.screenOptions.showSlotDarkeningEffect": "Show Slot Darkening Effect", + "text.config.accessories.option.screenOptions.showSlotDarkeningEffect.tooltip": "Toggles if slot darkening for equipping or unequipping items are shown within the Accessories Screen", + "text.config.accessories.section.legacy": "Original Screen", + "text.config.accessories.option.screenOptions.showGroupTabs": "Show quick seeking group tabs", + "text.config.accessories.option.screenOptions.showGroupTabs.tooltip": "Toggles the group tabs within the original screen to be shown or hidden.", "text.config.accessories.section.hover": "Hovered Effects", - "text.config.accessories.category.screenOptions.hoveredOptions": "Hovered Options", - "text.config.accessories.category.screenOptions.hoveredOptions.tooltip": [ - "Options to control the hovered entry rendering effects." - ], - + "text.config.accessories.category.screenOptions.hoveredOptions.tooltip": "Options to control the hovered entry rendering effects.", "text.config.accessories.option.screenOptions.hoveredOptions.brightenHovered": "Brighten Hovered", "text.config.accessories.option.screenOptions.hoveredOptions.cycleBrightness": "Cycle Brightness", - "text.config.accessories.option.screenOptions.hoveredOptions.line": "Draw Line", - "text.config.accessories.option.screenOptions.hoveredOptions.clickbait": "Clickbait", - "text.config.accessories.category.screenOptions.unHoveredOptions": "UnHovered Options", - "text.config.accessories.category.screenOptions.unHoveredOptions.tooltip": [ - "Options to control the non hovered entries rendering effects." - ], - + "text.config.accessories.category.screenOptions.unHoveredOptions.tooltip": "Options to control the non hovered entries rendering effects.", "text.config.accessories.option.screenOptions.unHoveredOptions.renderUnHovered": "Render UnHovered", "text.config.accessories.option.screenOptions.unHoveredOptions.darkenUnHovered": "Darken UnHovered", "text.config.accessories.option.screenOptions.unHoveredOptions.darkenedBrightness": "Darkened Brightness", "text.config.accessories.option.screenOptions.unHoveredOptions.darkenedOpacity": "Darkened Opacity", - "text.config.accessories.option.disabledDefaultRenders": "Disabled Default Renderers", - "text.config.accessories.option.disabledDefaultRenders.tooltip": [ - "Useful to disable default rendering for a given slot either\n", - "for specifically block or/and item renderings" - ], - + "text.config.accessories.option.disabledDefaultRenders.tooltip": "Useful to disable default rendering for a given slot either\nfor specifically block or/and item renderings", "text.config.accessories.option.clientOptions.disabledDefaultRenders.slotType": "Slot", "text.config.accessories.option.clientOptions.disabledDefaultRenders.targetType": "Type", - "text.config.accessories.enum.targetType.item": "Item", "text.config.accessories.enum.targetType.block": "Block", "text.config.accessories.enum.targetType.all": "All", - "text.config.accessories.option.modifiers": "Slot Amount Modifiers", - "text.config.accessories.option.modifiers.tooltip": [ - "Useful to add offset values to a given slot type without\n", - "needing a datapack as it allows for both positive or\n", - "negative offset value." - ], - + "text.config.accessories.option.modifiers.tooltip": "Useful to add offset values to a given slot type without\nneeding a datapack as it allows for both positive or\nnegative offset value.", "text.config.accessories.option.modifiers.slotType": "Slot", - "text.config.accessories.option.modifiers.amount": "Offset" + "text.config.accessories.option.modifiers.amount": "Offset", + + "text.config.accessories.enum.tooltipInfoType.all": "All", + "text.config.accessories.enum.tooltipInfoType.advanced": "Advanced", + "text.config.accessories.enum.tooltipInfoType.basic": "Basic", + "text.config.accessories.enum.tooltipInfoType.disabled": "Disabled" } diff --git a/fabric/build.gradle.kts b/fabric/build.gradle.kts index 60f789e6a..e056a265e 100644 --- a/fabric/build.gradle.kts +++ b/fabric/build.gradle.kts @@ -1,4 +1,3 @@ -import io.wispforest.helpers.Utils import io.wispforest.helpers.Extensions.modrinth import io.wispforest.helpers.Extensions.modrinthImplementation @@ -10,19 +9,18 @@ plugins { dependencies { // Core Libs - modImplementation(libs.fabric.loader) - modImplementation(libs.fabric.api) + implementation(libs.fabric.loader) + implementation(libs.fabric.api) // -- // General Libs - modCompileOnly(libs.modmenu) - modLocalRuntime(libs.modmenu) + compileOnly(libs.modmenu) { isTransitive = false } //-- -// modrinth(this::modLocalRuntime, "ok-boomer" to "0.1.3+1.21") -// modrinth(this::modLocalRuntime, "sodium" to "${libs.versions.sodium.get()}-fabric") +// modrinth(this::runtimeOnly, "ok-boomer" to "0.1.3+1.21") + modrinth(this::runtimeOnly, "sodium" to "${libs.versions.sodium.get()}-fabric") - modCompileOnly(libs.trinkets) + // compileOnly(libs.trinkets) // TODO: update trinkets for 26.1 } repositories {} \ No newline at end of file diff --git a/fabric/src/main/java/io/wispforest/accessories/fabric/AccessoriesFabric.java b/fabric/src/main/java/io/wispforest/accessories/fabric/AccessoriesFabric.java index 8c85e152d..a20607a4b 100644 --- a/fabric/src/main/java/io/wispforest/accessories/fabric/AccessoriesFabric.java +++ b/fabric/src/main/java/io/wispforest/accessories/fabric/AccessoriesFabric.java @@ -1,6 +1,5 @@ package io.wispforest.accessories.fabric; -import com.google.common.reflect.Reflection; import com.mojang.brigadier.arguments.ArgumentType; import io.wispforest.accessories.Accessories; import io.wispforest.accessories.api.AccessoriesCapability; @@ -28,7 +27,7 @@ import net.fabricmc.fabric.api.attachment.v1.AttachmentType; import net.fabricmc.fabric.api.command.v2.ArgumentTypeRegistry; import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; -import net.fabricmc.fabric.api.entity.event.v1.ServerEntityWorldChangeEvents; +import net.fabricmc.fabric.api.entity.event.v1.ServerEntityLevelChangeEvents; import net.fabricmc.fabric.api.entity.event.v1.ServerPlayerEvents; import net.fabricmc.fabric.api.event.Event; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerEntityEvents; @@ -36,8 +35,9 @@ import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; import net.fabricmc.fabric.api.event.player.UseEntityCallback; import net.fabricmc.fabric.api.event.player.UseItemCallback; -import net.fabricmc.fabric.api.gamerule.v1.GameRuleFactory; -import net.fabricmc.fabric.api.gamerule.v1.GameRuleRegistry; +import net.fabricmc.fabric.api.gamerule.v1.GameRuleBuilder; +import net.minecraft.world.level.gamerules.GameRule; +import net.minecraft.world.level.gamerules.GameRuleCategory; import net.fabricmc.fabric.api.item.v1.DefaultItemComponentEvents; import net.fabricmc.fabric.api.lookup.v1.entity.EntityApiLookup; import net.fabricmc.fabric.api.resource.ResourceManagerHelper; @@ -45,7 +45,7 @@ import net.fabricmc.fabric.api.resource.v1.ResourceLoader; import net.minecraft.core.component.DataComponentType; import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.server.packs.PackType; import net.minecraft.server.packs.resources.ResourceManager; import net.minecraft.server.packs.resources.ResourceManagerReloadListener; @@ -53,7 +53,6 @@ import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.item.Item; -import net.minecraft.world.level.GameRules; import java.util.Objects; @@ -88,7 +87,7 @@ public void onInitialize() { AccessoriesNetworking.init(); SyncedDataHelperManager.init(AccessoriesNetworking.CHANNEL, playerConsumer -> { - ResourceLocation beforeDefaultPhase = Accessories.of("before_default_phase"); + Identifier beforeDefaultPhase = Accessories.of("before_default_phase"); ServerLifecycleEvents.SYNC_DATA_PACK_CONTENTS.addPhaseOrdering(beforeDefaultPhase, Event.DEFAULT_PHASE); @@ -101,7 +100,7 @@ public void onInitialize() { Accessories.registerCriteria(); CommandGenerators.registerAllArgumentTypes(new ArgumentRegistrationCallback() { @Override - public , T> RecordArgumentTypeInfo register(ResourceLocation location, Class clazz, RecordArgumentTypeInfo info) { + public , T> RecordArgumentTypeInfo register(Identifier location, Class clazz, RecordArgumentTypeInfo info) { ArgumentTypeRegistry.registerArgumentType(location, clazz, info); return info; @@ -131,7 +130,7 @@ public , T> RecordArgumentTypeInfo register(Reso UseEntityCallback.EVENT.register((player, level, hand, entity, hitResult) -> AccessoriesEventHandler.attemptEquipOnEntity(player, hand, entity)); - ServerTickEvents.START_WORLD_TICK.register(AccessoriesEventHandler::onWorldTick); + ServerTickEvents.START_LEVEL_TICK.register(AccessoriesEventHandler::onWorldTick); ServerLifecycleEvents.SYNC_DATA_PACK_CONTENTS.register((player, joined) -> { if(!joined) return; @@ -170,7 +169,7 @@ public , T> RecordArgumentTypeInfo register(Reso }); ResourceLoader.get(PackType.SERVER_DATA) - .registerReloader( + .registerReloadListener( Accessories.DATA_RELOAD_HOOK, (ResourceManagerReloadListener) manager -> AccessoriesEventHandler.dataReloadOccurred = true ); @@ -184,7 +183,7 @@ public void addTo(Item item, DataComponentType componentType, T component }); }); - ServerEntityWorldChangeEvents.AFTER_PLAYER_CHANGE_WORLD.register((player, origin, destination) -> { + ServerEntityLevelChangeEvents.AFTER_PLAYER_CHANGE_LEVEL.register((player, origin, destination) -> { AccessoriesNetworking.CHANNEL.serverHandle(player).send(new InvalidateEntityCache(player.getId())); AccessoriesEventHandler.onTracking(player, player); @@ -200,6 +199,10 @@ public void addTo(Item item, DataComponentType componentType, T component SyncEntireContainer.syncToAllTrackingAndSelf(newPlayer); }); - Reflection.initialize(AccessoriesGameRules.class); + // Register game rule for keeping accessory inventory on death + GameRule keepAccessoryInventory = GameRuleBuilder.forBoolean(false) + .category(GameRuleCategory.PLAYER) + .buildAndRegister(Accessories.of("keepaccessoryinventory")); + AccessoriesGameRules.init(keepAccessoryInventory); } } \ No newline at end of file diff --git a/fabric/src/main/java/io/wispforest/accessories/fabric/AccessoriesFabricInternals.java b/fabric/src/main/java/io/wispforest/accessories/fabric/AccessoriesFabricInternals.java index f8fbf2f47..df9474e1b 100644 --- a/fabric/src/main/java/io/wispforest/accessories/fabric/AccessoriesFabricInternals.java +++ b/fabric/src/main/java/io/wispforest/accessories/fabric/AccessoriesFabricInternals.java @@ -12,28 +12,32 @@ import io.wispforest.accessories.menu.variants.AccessoriesMenuBase; import io.wispforest.endec.Endec; import io.wispforest.owo.serialization.CodecUtils; -import net.fabricmc.fabric.api.gamerule.v1.GameRuleFactory; -import net.fabricmc.fabric.api.gamerule.v1.GameRuleRegistry; import net.fabricmc.fabric.api.resource.v1.ResourceLoader; -import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerFactory; -import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerType; +import net.fabricmc.fabric.api.menu.v1.ExtendedMenuProvider; +import net.fabricmc.fabric.api.menu.v1.ExtendedMenuType; +import net.fabricmc.fabric.api.transfer.v1.fluid.FluidStorage; import net.fabricmc.fabric.api.transfer.v1.item.ItemVariant; import net.fabricmc.fabric.api.transfer.v1.item.PlayerInventoryStorage; import net.fabricmc.fabric.api.transfer.v1.transaction.Transaction; import net.fabricmc.fabric.impl.resource.conditions.ResourceConditionsImpl; +import net.minecraft.util.Util; import net.minecraft.core.Holder; import net.minecraft.core.HolderLookup; import net.minecraft.core.Registry; +import net.minecraft.core.component.DataComponents; import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.network.chat.CommonComponents; import net.minecraft.network.chat.Component; import net.minecraft.resources.RegistryOps; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.packs.PackType; import net.minecraft.server.packs.resources.PreparableReloadListener; import net.minecraft.server.packs.resources.SimplePreparableReloadListener; import net.minecraft.tags.TagKey; +import net.minecraft.world.effect.MobEffect; +import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.ai.attributes.Attribute; @@ -47,7 +51,10 @@ import net.minecraft.world.item.TooltipFlag; import net.minecraft.world.item.component.ItemAttributeModifiers; import net.minecraft.world.item.component.TooltipDisplay; -import net.minecraft.world.level.GameRules; +import net.minecraft.world.level.gamerules.GameRules; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.material.Fluid; import org.apache.commons.lang3.function.TriFunction; import org.jetbrains.annotations.Nullable; @@ -95,16 +102,16 @@ public void giveItemToPlayer(ServerPlayer player, ItemStack stack) { } } - public boolean isValidOnConditions(JsonObject object, String dataType, ResourceLocation key, SimplePreparableReloadListener listener, @Nullable RegistryOps.RegistryInfoLookup registryInfo) { + public boolean isValidOnConditions(JsonObject object, String dataType, Identifier key, SimplePreparableReloadListener listener, @Nullable RegistryOps.RegistryInfoLookup registryInfo) { return ResourceConditionsImpl.applyResourceConditions(object, dataType, key, registryInfo); } - public MenuType registerMenuType(ResourceLocation location, Endec endec, TriFunction func){ - return Registry.register(BuiltInRegistries.MENU, location, new ExtendedScreenHandlerType<>(func::apply, CodecUtils.toPacketCodec(endec))); + public MenuType registerMenuType(Identifier location, Endec endec, TriFunction func){ + return Registry.register(BuiltInRegistries.MENU, location, new ExtendedMenuType<>(func::apply, CodecUtils.toPacketCodec(endec))); } public void openAccessoriesMenu(Player player, AccessoriesMenuVariant variant, @Nullable LivingEntity targetEntity, @Nullable ItemStack carriedStack) { - player.openMenu(new ExtendedScreenHandlerFactory() { + player.openMenu(new ExtendedMenuProvider() { @Override public AccessoriesMenuData getScreenOpeningData(ServerPlayer player) { return AccessoriesMenuData.of(targetEntity, ((AccessoriesMenuBase) player.containerMenu)); @@ -139,14 +146,14 @@ public void registerLoader(PackType packType, IdentifiedResourceReloadListener d var id = dataLoader.getId(); - loader.registerReloader(id, dataLoader); + loader.registerReloadListener(id, dataLoader); for (var dependencyId : dataLoader.getDependencyIds()) { - loader.addReloaderOrdering(dependencyId, id); + loader.addListenerOrdering(dependencyId, id); } if (dataLoader instanceof EndecDataLoader endecDataLoader) { - endecDataLoader.setRegistriesAccess(sharedState -> sharedState.get(ResourceLoader.RELOADER_REGISTRY_LOOKUP_KEY)); + endecDataLoader.setRegistriesAccess(sharedState -> sharedState.get(ResourceLoader.REGISTRY_LOOKUP_KEY)); } } @@ -154,4 +161,26 @@ public void registerLoader(PackType packType, IdentifiedResourceReloadListener d public String getTagTranslation(TagKey tagKey) { return tagKey.getTranslationKey(); } + + @Override + public String geEntryTranslation(Holder entry) { + var value = entry.value(); + + return switch (value) { + case Item item -> item.getDescriptionId(); + case Block block -> block.getDescriptionId(); + case EntityType type -> type.getDescriptionId(); + case MobEffect effect -> effect.getDescriptionId(); + case Attribute attribute -> attribute.getDescriptionId(); + case Fluid fluid -> { + var fluidBlock = fluid.defaultFluidState().createLegacyBlock().getBlock(); + + // Some non-placeable fluids use air as their fluid block, in that case infer translation key from the fluid id. + yield fluidBlock == Blocks.AIR + ? Util.makeDescriptionId("block", BuiltInRegistries.FLUID.getKey(fluid)) + : fluidBlock.getDescriptionId(); + } + default -> value.toString(); + }; + } } diff --git a/fabric/src/main/java/io/wispforest/accessories/fabric/client/AccessoriesClientFabric.java b/fabric/src/main/java/io/wispforest/accessories/fabric/client/AccessoriesClientFabric.java index 8b1c0e337..6db5030d5 100644 --- a/fabric/src/main/java/io/wispforest/accessories/fabric/client/AccessoriesClientFabric.java +++ b/fabric/src/main/java/io/wispforest/accessories/fabric/client/AccessoriesClientFabric.java @@ -15,9 +15,9 @@ import net.fabricmc.api.ClientModInitializer; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.fabric.api.client.item.v1.ItemTooltipCallback; -import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; +import net.fabricmc.fabric.api.client.keymapping.v1.KeyMappingHelper; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents; -import net.fabricmc.fabric.api.client.rendering.v1.LivingEntityFeatureRendererRegistrationCallback; +import net.fabricmc.fabric.api.client.rendering.v1.LivingEntityRenderLayerRegistrationCallback; import net.fabricmc.fabric.api.event.Event; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.screens.MenuScreens; @@ -71,28 +71,11 @@ public void onInitializeClient() { // }); - KeyBindingHelper.registerKeyBinding(AccessoriesClient.OPEN_SCREEN); + KeyMappingHelper.registerKeyMapping(AccessoriesClient.OPEN_SCREEN); - ClientTickEvents.START_CLIENT_TICK.register(client -> { - if (AccessoriesClient.OPEN_SCREEN.consumeClick()){ - var player = client.player; + ClientTickEvents.START_CLIENT_TICK.register(AccessoriesClient::handleKeyMappings); - if (Accessories.config().screenOptions.prioritizeCreativeScreen() && player != null && player.isCreative()) { - if (client.gameMode.isServerControlledInventory()) { - player.sendOpenInventory(); - } else { - client.getTutorial().onOpenInventory(); - client.setScreen(new InventoryScreen(player)); - } - - return; - } - - AccessoriesClient.openScreenFromKey(); - } - }); - - LivingEntityFeatureRendererRegistrationCallback.EVENT.register((entityType, entityRenderer, registrationHelper, context) -> { + LivingEntityRenderLayerRegistrationCallback.EVENT.register((entityType, entityRenderer, registrationHelper, context) -> { if(!(entityRenderer.getModel() instanceof HumanoidModel)) return; // TODO: CONFIRM THIS IS CORRECT! diff --git a/fabric/src/main/java/io/wispforest/accessories/fabric/data/AccessoriesDataGenEntrypoint.java b/fabric/src/main/java/io/wispforest/accessories/fabric/data/AccessoriesDataGenEntrypoint.java index 9e1f356b2..3c49240b6 100644 --- a/fabric/src/main/java/io/wispforest/accessories/fabric/data/AccessoriesDataGenEntrypoint.java +++ b/fabric/src/main/java/io/wispforest/accessories/fabric/data/AccessoriesDataGenEntrypoint.java @@ -11,7 +11,7 @@ import net.fabricmc.fabric.api.datagen.v1.FabricDataGenerator; import net.minecraft.core.HolderLookup; import net.minecraft.core.RegistrySetBuilder; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.world.entity.EntityType; public class AccessoriesDataGenEntrypoint implements DataGeneratorEntrypoint { @@ -64,7 +64,7 @@ protected void buildData(HolderLookup.Provider provider, EntityBindingOutput out var modid = "accessories"; output.accept( - ResourceLocation.fromNamespaceAndPath(modid, "test_binding"), + Identifier.fromNamespaceAndPath(modid, "test_binding"), this.builder() .slots("test") .entityType(EntityType.PLAYER) diff --git a/fabric/src/main/java/io/wispforest/accessories/fabric/mixin/client/AbstractContainerScreenMixin.java b/fabric/src/main/java/io/wispforest/accessories/fabric/mixin/client/AbstractContainerScreenMixin.java index 2a4c69ca3..fd8e90c9b 100644 --- a/fabric/src/main/java/io/wispforest/accessories/fabric/mixin/client/AbstractContainerScreenMixin.java +++ b/fabric/src/main/java/io/wispforest/accessories/fabric/mixin/client/AbstractContainerScreenMixin.java @@ -6,7 +6,7 @@ import io.wispforest.accessories.client.AccessoriesClient; import io.wispforest.accessories.pond.ContainerScreenExtension; import net.minecraft.client.KeyMapping; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; import net.minecraft.client.input.KeyEvent; import net.minecraft.world.inventory.Slot; @@ -20,15 +20,15 @@ public abstract class AbstractContainerScreenMixin implements ContainerScreenExt @Shadow @Nullable protected Slot hoveredSlot; - @WrapOperation(method = "renderContents", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/inventory/AbstractContainerScreen;renderSlotHighlightFront(Lnet/minecraft/client/gui/GuiGraphics;)V")) - private void accessories$isHoveringOverrideFront(AbstractContainerScreen instance, GuiGraphics guiGraphics, Operation original, @Local(argsOnly = true, ordinal = 0) int mouseX, @Local(argsOnly = true, ordinal = 1) int mouseY){ + @WrapOperation(method = "extractContents", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/inventory/AbstractContainerScreen;extractSlotHighlightFront(Lnet/minecraft/client/gui/GuiGraphicsExtractor;)V")) + private void accessories$isHoveringOverrideFront(AbstractContainerScreen instance, GuiGraphicsExtractor guiGraphics, Operation original, @Local(argsOnly = true, ordinal = 0) int mouseX, @Local(argsOnly = true, ordinal = 1) int mouseY){ var override = this.isHovering_Rendering(this.hoveredSlot, mouseX, mouseY); if (override == null || override) original.call(instance, guiGraphics); } - @WrapOperation(method = "renderContents", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/inventory/AbstractContainerScreen;renderSlotHighlightBack(Lnet/minecraft/client/gui/GuiGraphics;)V")) - private void accessories$isHoveringOverrideBack(AbstractContainerScreen instance, GuiGraphics guiGraphics, Operation original, @Local(argsOnly = true, ordinal = 0) int mouseX, @Local(argsOnly = true, ordinal = 1) int mouseY){ + @WrapOperation(method = "extractContents", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/inventory/AbstractContainerScreen;extractSlotHighlightBack(Lnet/minecraft/client/gui/GuiGraphicsExtractor;)V")) + private void accessories$isHoveringOverrideBack(AbstractContainerScreen instance, GuiGraphicsExtractor guiGraphics, Operation original, @Local(argsOnly = true, ordinal = 0) int mouseX, @Local(argsOnly = true, ordinal = 1) int mouseY){ var override = this.isHovering_Rendering(this.hoveredSlot, mouseX, mouseY); if (override == null || override) original.call(instance, guiGraphics); @@ -36,6 +36,6 @@ public abstract class AbstractContainerScreenMixin implements ContainerScreenExt @WrapOperation(method = "keyPressed", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/KeyMapping;matches(Lnet/minecraft/client/input/KeyEvent;)Z", ordinal = 0)) private boolean accessories$adjustCloseCheck(KeyMapping instance, KeyEvent arg, Operation original) { - return original.call(instance, arg) || original.call(AccessoriesClient.OPEN_SCREEN, arg); + return original.call(instance, arg) || AccessoriesClient.isInventoryKey(keyMapping -> original.call(keyMapping, arg)); } } \ No newline at end of file diff --git a/fabric/src/main/java/io/wispforest/accessories/fabric/mixin/trinkets/LivingEntityTrinketComponentMixin.java b/fabric/src/main/java/io/wispforest/accessories/fabric/mixin/trinkets/LivingEntityTrinketComponentMixin.java index 0de099f94..d3cb22067 100644 --- a/fabric/src/main/java/io/wispforest/accessories/fabric/mixin/trinkets/LivingEntityTrinketComponentMixin.java +++ b/fabric/src/main/java/io/wispforest/accessories/fabric/mixin/trinkets/LivingEntityTrinketComponentMixin.java @@ -2,7 +2,6 @@ import com.llamalad7.mixinextras.sugar.Local; import com.llamalad7.mixinextras.sugar.ref.LocalRef; -import dev.emi.trinkets.api.LivingEntityTrinketComponent; import net.minecraft.core.HolderLookup; import net.minecraft.nbt.CompoundTag; import org.spongepowered.asm.mixin.Mixin; @@ -12,7 +11,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Pseudo -@Mixin(value = LivingEntityTrinketComponent.class, remap = false) +@Mixin(targets = "dev.emi.trinkets.api.LivingEntityTrinketComponent", remap = false) public class LivingEntityTrinketComponentMixin { @Inject(method = "readFromNbt", at = @At("HEAD"), remap = false) diff --git a/fabric/src/main/resources/accessories-fabric.accesswidener b/fabric/src/main/resources/accessories-fabric.accesswidener index 42420b1f9..9beb75eef 100644 --- a/fabric/src/main/resources/accessories-fabric.accesswidener +++ b/fabric/src/main/resources/accessories-fabric.accesswidener @@ -1,4 +1,4 @@ -accessWidener v2 named +accessWidener v2 official accessible class net/minecraft/resources/RegistryOps$HolderLookupAdapter extendable class net/minecraft/resources/RegistryOps$HolderLookupAdapter diff --git a/fabric/src/testmod/java/io/wispforest/testccessories/fabric/TestMenu.java b/fabric/src/testmod/java/io/wispforest/testccessories/fabric/TestMenu.java index 1067f0221..b6c919133 100644 --- a/fabric/src/testmod/java/io/wispforest/testccessories/fabric/TestMenu.java +++ b/fabric/src/testmod/java/io/wispforest/testccessories/fabric/TestMenu.java @@ -26,10 +26,9 @@ public TestMenu(int containerId, Inventory playerInventory) { baseY += 18; - if(generator != null) { - this.addedSlots = generator.padding(1) - .row(); - } + baseY += 4; + + if(generator != null) this.addedSlots = generator.row(); for(int i = 0; i < 3; ++i) { for(int j = 0; j < 9; ++j) { diff --git a/fabric/src/testmod/java/io/wispforest/testccessories/fabric/Testccessories.java b/fabric/src/testmod/java/io/wispforest/testccessories/fabric/Testccessories.java index 1f917ae89..ebd286019 100644 --- a/fabric/src/testmod/java/io/wispforest/testccessories/fabric/Testccessories.java +++ b/fabric/src/testmod/java/io/wispforest/testccessories/fabric/Testccessories.java @@ -7,7 +7,7 @@ import net.fabricmc.api.ModInitializer; import net.minecraft.core.Registry; import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.world.flag.FeatureFlags; import net.minecraft.world.inventory.MenuType; @@ -30,11 +30,13 @@ public void onInitialize() { UniqueSlotHandling.EVENT.register(UniqueSlotTest.INSTANCE); TestItems.init(); + } - AccessoriesNetworking.CHANNEL.registerClientboundDeferred(TestScreenPacket.class, TestScreenPacket.ENDEC); + public static Identifier of(String path) { + return Identifier.fromNamespaceAndPath(MODID, path); } - public static ResourceLocation of(String path) { - return ResourceLocation.fromNamespaceAndPath(MODID, path); + public static void initNetworkPackets() { + AccessoriesNetworking.CHANNEL.registerServerbound(TestScreenPacket.class, TestScreenPacket.ENDEC, AccessoriesNetworking.serverHandler(TestScreenPacket::handlePacket)); } } \ No newline at end of file diff --git a/fabric/src/testmod/java/io/wispforest/testccessories/fabric/UniqueSlotTest.java b/fabric/src/testmod/java/io/wispforest/testccessories/fabric/UniqueSlotTest.java index c03568df2..159cdab0d 100644 --- a/fabric/src/testmod/java/io/wispforest/testccessories/fabric/UniqueSlotTest.java +++ b/fabric/src/testmod/java/io/wispforest/testccessories/fabric/UniqueSlotTest.java @@ -1,11 +1,12 @@ package io.wispforest.testccessories.fabric; -import io.wispforest.accessories.api.slot.SlotBasedPredicate; -import io.wispforest.accessories.api.slot.SlotPredicateRegistry; +import io.wispforest.accessories.api.action.ActionResponse; import io.wispforest.accessories.api.slot.SlotTypeReference; import io.wispforest.accessories.api.slot.UniqueSlotHandling; -import net.fabricmc.fabric.api.util.TriState; -import net.minecraft.resources.ResourceLocation; +import io.wispforest.accessories.api.slot.validator.SlotValidator; +import io.wispforest.accessories.api.slot.validator.SlotValidatorRegistry; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.Identifier; import net.minecraft.tags.BlockTags; import net.minecraft.world.entity.EntityType; import net.minecraft.world.item.BlockItem; @@ -13,17 +14,19 @@ public class UniqueSlotTest implements UniqueSlotHandling.RegistrationCallback { - private final ResourceLocation slotPredicate1 = Testccessories.of("test_slot_1_equipment"); - private final ResourceLocation slotPredicate2 = Testccessories.of("test_slot_2_equipment"); - private final ResourceLocation slotPredicate3 = Testccessories.of("test_slot_3_equipment"); + private final Identifier slotPredicate1 = Testccessories.of("test_slot_1_equipment"); + private final Identifier slotPredicate2 = Testccessories.of("test_slot_2_equipment"); + private final Identifier slotPredicate3 = Testccessories.of("test_slot_3_equipment"); public static final UniqueSlotTest INSTANCE = new UniqueSlotTest(); private UniqueSlotTest(){ - SlotPredicateRegistry.register(slotPredicate1, SlotBasedPredicate.ofItem(item -> item.equals(TestItems.testItem1))); - SlotPredicateRegistry.register(slotPredicate2, SlotBasedPredicate.ofItem(item -> item.equals(TestItems.testItem2))); - SlotPredicateRegistry.register(slotPredicate3, (level, slotType, slot, stack) -> { - return (stack.getItem() instanceof BlockItem blockItem && blockItem.getBlock().builtInRegistryHolder().is(BlockTags.BEDS)) ? TriState.TRUE : TriState.DEFAULT; + SlotValidatorRegistry.register(slotPredicate1, SlotValidator.ofItem(item -> item.equals(TestItems.testItem1))); + SlotValidatorRegistry.register(slotPredicate2, SlotValidator.ofItem(item -> item.equals(TestItems.testItem2))); + SlotValidatorRegistry.register(slotPredicate3, (level, slotType, slot, stack, buffer) -> { + if (stack.getItem() instanceof BlockItem blockItem && blockItem.getBlock().builtInRegistryHolder().is(BlockTags.BEDS)) { + buffer.respondWith(ActionResponse.of(true, Component.literal("The bed fits within the bed slot!"))); + } }); } diff --git a/fabric/src/testmod/java/io/wispforest/testccessories/fabric/accessories/PointedDripstoneAccessory.java b/fabric/src/testmod/java/io/wispforest/testccessories/fabric/accessories/PointedDripstoneAccessory.java index ae40ea78b..822fc5917 100644 --- a/fabric/src/testmod/java/io/wispforest/testccessories/fabric/accessories/PointedDripstoneAccessory.java +++ b/fabric/src/testmod/java/io/wispforest/testccessories/fabric/accessories/PointedDripstoneAccessory.java @@ -23,7 +23,7 @@ import net.minecraft.client.renderer.entity.state.LivingEntityRenderState; import net.minecraft.client.renderer.item.ItemStackRenderState; import net.minecraft.client.renderer.texture.OverlayTexture; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.world.entity.HumanoidArm; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.ai.attributes.AttributeModifier; @@ -33,7 +33,7 @@ public class PointedDripstoneAccessory implements Accessory { - private static final ResourceLocation ATTACK_DAMAGE_LOCATION = Testccessories.of("pointed_dripstone_accessory_attack_damage"); + private static final Identifier ATTACK_DAMAGE_LOCATION = Testccessories.of("pointed_dripstone_accessory_attack_damage"); @Environment(EnvType.CLIENT) public static void clientInit() { diff --git a/fabric/src/testmod/java/io/wispforest/testccessories/fabric/accessories/RingIncreaserAccessory.java b/fabric/src/testmod/java/io/wispforest/testccessories/fabric/accessories/RingIncreaserAccessory.java index d99895383..0c7d2f1ef 100644 --- a/fabric/src/testmod/java/io/wispforest/testccessories/fabric/accessories/RingIncreaserAccessory.java +++ b/fabric/src/testmod/java/io/wispforest/testccessories/fabric/accessories/RingIncreaserAccessory.java @@ -1,24 +1,29 @@ package io.wispforest.testccessories.fabric.accessories; import com.google.common.collect.HashMultimap; +import io.wispforest.accessories.api.action.ActionResponseBuffer; +import io.wispforest.accessories.api.action.HolderSetValidationResponse; import io.wispforest.accessories.api.core.Accessory; import io.wispforest.accessories.api.core.AccessoryRegistry; import io.wispforest.accessories.api.slot.SlotReference; import io.wispforest.testccessories.fabric.Testccessories; import net.minecraft.core.component.DataComponents; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; +import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.ai.attributes.AttributeModifier; import net.minecraft.world.item.DyeColor; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; +import java.util.List; + public class RingIncreaserAccessory implements Accessory { public static void init(){ AccessoryRegistry.register(Items.BEACON, new RingIncreaserAccessory()); } - private static final ResourceLocation ringAdditionLocation = Testccessories.of("additional_rings"); + private static final Identifier ringAdditionLocation = Testccessories.of("additional_rings"); @Override public void onEquip(ItemStack stack, SlotReference reference) { @@ -41,4 +46,9 @@ public void onUnequip(ItemStack stack, SlotReference reference) { reference.capability().removeSlotModifiers(map); } + + @Override + public void canEquip(ItemStack stack, SlotReference reference, ActionResponseBuffer buffer) { + buffer.respondWith(new HolderSetValidationResponse<>(List.of(EntityType.PLAYER.builtInRegistryHolder()), reference.entity().getType().builtInRegistryHolder())); + } } diff --git a/fabric/src/testmod/java/io/wispforest/testccessories/fabric/accessories/WaterBreathingAccessory.java b/fabric/src/testmod/java/io/wispforest/testccessories/fabric/accessories/WaterBreathingAccessory.java index e412d46ea..f10f86f98 100644 --- a/fabric/src/testmod/java/io/wispforest/testccessories/fabric/accessories/WaterBreathingAccessory.java +++ b/fabric/src/testmod/java/io/wispforest/testccessories/fabric/accessories/WaterBreathingAccessory.java @@ -7,7 +7,7 @@ import io.wispforest.testccessories.fabric.TestItems; import io.wispforest.testccessories.fabric.Testccessories; import net.minecraft.core.component.DataComponents; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.ai.attributes.AttributeModifier; import net.minecraft.world.entity.ai.attributes.Attributes; @@ -16,7 +16,7 @@ public class WaterBreathingAccessory implements Accessory { - private static final ResourceLocation GRAVITY_LOCATION = Testccessories.of("gravity_accessory_adjustment"); + private static final Identifier GRAVITY_LOCATION = Testccessories.of("gravity_accessory_adjustment"); public static void init() { AccessoryRegistry.register(TestItems.testItem1, new WaterBreathingAccessory()); diff --git a/fabric/src/testmod/java/io/wispforest/testccessories/fabric/client/TestScreen.java b/fabric/src/testmod/java/io/wispforest/testccessories/fabric/client/TestScreen.java index fa70acba1..be35c8f12 100644 --- a/fabric/src/testmod/java/io/wispforest/testccessories/fabric/client/TestScreen.java +++ b/fabric/src/testmod/java/io/wispforest/testccessories/fabric/client/TestScreen.java @@ -9,7 +9,7 @@ import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; import net.minecraft.client.gui.screens.inventory.MenuAccess; import net.minecraft.network.chat.Component; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.inventory.Slot; @@ -17,12 +17,15 @@ public class TestScreen extends AbstractContainerScreen implements MenuAccess { - private static final ResourceLocation SLOT_FRAME = Accessories.of("textures/gui/slot.png"); + private static final Identifier SLOT_FRAME = Accessories.of("textures/gui/theme/light/slot.png"); - private static final ResourceLocation BACKGROUND_PATCH = Accessories.of("background_patch"); + private static final Identifier BACKGROUND_PATCH = Accessories.of("background_patch"); public TestScreen(TestMenu menu, Inventory playerInventory, Component title) { super(menu, playerInventory, title); + + inventoryLabelY = 42069; + titleLabelX -= 10; } @Override @@ -43,13 +46,15 @@ protected void renderBg(GuiGraphics guiGraphics, float partialTick, int mouseX, } } - var padding = 4; + var titleOffset = 12; + + var padding = 6; var width = (maxX - minX) + 18 + (padding * 2); - var height = (maxY - minY) + 18 + (padding * 2); + var height = (maxY - minY) + 18 + (padding * 2) + titleOffset; var startX = minX - padding; - var startY = minY - padding; + var startY = minY - titleOffset - padding; guiGraphics.push().translate((float)leftPos, (float)topPos); diff --git a/fabric/src/testmod/java/io/wispforest/testccessories/fabric/client/TestccessoriesClientFabric.java b/fabric/src/testmod/java/io/wispforest/testccessories/fabric/client/TestccessoriesClient.java similarity index 90% rename from fabric/src/testmod/java/io/wispforest/testccessories/fabric/client/TestccessoriesClientFabric.java rename to fabric/src/testmod/java/io/wispforest/testccessories/fabric/client/TestccessoriesClient.java index 4528d4044..4485a9dfb 100644 --- a/fabric/src/testmod/java/io/wispforest/testccessories/fabric/client/TestccessoriesClientFabric.java +++ b/fabric/src/testmod/java/io/wispforest/testccessories/fabric/client/TestccessoriesClient.java @@ -16,7 +16,7 @@ import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.world.item.Items; -public class TestccessoriesClientFabric implements ClientModInitializer { +public class TestccessoriesClient implements ClientModInitializer { @Override public void onInitializeClient() { AppleAccessory.clientInit(); @@ -48,7 +48,5 @@ public void onInitializeClient() { }); RegistryEntryAddedCallback.event(BuiltInRegistries.ITEM).register((i, location, item) -> AccessoriesRendererRegistry.bindItemToArmorRenderer(item)); - - AccessoriesNetworking.CHANNEL.registerClientbound(TestScreenPacket.class, TestScreenPacket.ENDEC, AccessoriesNetworking.clientHandler(TestScreenPacket::handlePacket)); } } \ No newline at end of file diff --git a/fabric/src/testmod/java/io/wispforest/testccessories/fabric/mixin/AccessoriesNetworkingMixin.java b/fabric/src/testmod/java/io/wispforest/testccessories/fabric/mixin/AccessoriesNetworkingMixin.java new file mode 100644 index 000000000..3e16eed9f --- /dev/null +++ b/fabric/src/testmod/java/io/wispforest/testccessories/fabric/mixin/AccessoriesNetworkingMixin.java @@ -0,0 +1,16 @@ +package io.wispforest.testccessories.fabric.mixin; + +import io.wispforest.accessories.networking.AccessoriesNetworking; +import io.wispforest.testccessories.fabric.Testccessories; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(value = AccessoriesNetworking.class, remap = false) +public abstract class AccessoriesNetworkingMixin { + @Inject(method = "init", at = @At("TAIL")) + private static void registerOtherPackets(CallbackInfo ci) { + Testccessories.initNetworkPackets(); + } +} \ No newline at end of file diff --git a/fabric/src/testmod/resources/assets/testccessories/lang/en_us.json b/fabric/src/testmod/resources/assets/testccessories/lang/en_us.json index 6c426b426..b289dbda6 100644 --- a/fabric/src/testmod/resources/assets/testccessories/lang/en_us.json +++ b/fabric/src/testmod/resources/assets/testccessories/lang/en_us.json @@ -9,5 +9,6 @@ "advancement.testccessories.base.no_longer_lefthanded_drip.desc": "very cringe", "accessories.slot_group.testccessories": "Testccessories", "accessories.slot.testccessories.test_slot_1": "Test Slot 1", - "accessories.slot.testccessories.test_slot_2": "Test Slot 2" + "accessories.slot.testccessories.test_slot_2": "Test Slot 2", + "accessories.slot.testccessories.test_slot_3": "Test Slot 3" } \ No newline at end of file diff --git a/fabric/src/testmod/resources/data/testccessories/accessories/slot/something.json b/fabric/src/testmod/resources/data/testccessories/accessories/slot/something.json index a12ce2de4..56c72f0f0 100644 --- a/fabric/src/testmod/resources/data/testccessories/accessories/slot/something.json +++ b/fabric/src/testmod/resources/data/testccessories/accessories/slot/something.json @@ -1,6 +1,6 @@ { "order": 100, - "icon": "accessories:gui/slot/charm", + "icon": "accessories:container/slot/charm", "amount": 0, "operation": "SET" } \ No newline at end of file diff --git a/fabric/src/testmod/resources/fabric.mod.json b/fabric/src/testmod/resources/fabric.mod.json index cc5407318..4cc5a7987 100644 --- a/fabric/src/testmod/resources/fabric.mod.json +++ b/fabric/src/testmod/resources/fabric.mod.json @@ -19,7 +19,7 @@ "io.wispforest.testccessories.fabric.Testccessories" ], "client":[ - "io.wispforest.testccessories.fabric.client.TestccessoriesClientFabric" + "io.wispforest.testccessories.fabric.client.TestccessoriesClient" ] }, "mixins": [ @@ -39,7 +39,7 @@ "io/wispforest/accessories/pond/AccessoriesRenderStateAPI" ], "net/minecraft/class_1836": [ - "io/wispforest/accessories/pond/TooltipFlagExtension" + "io/wispforest/accessories/pond/TooltipFlagExtended" ] } } diff --git a/fabric/src/testmod/resources/testccessories-fabric.mixins.json b/fabric/src/testmod/resources/testccessories-fabric.mixins.json index ec50d8f55..2f12ebffe 100644 --- a/fabric/src/testmod/resources/testccessories-fabric.mixins.json +++ b/fabric/src/testmod/resources/testccessories-fabric.mixins.json @@ -6,6 +6,7 @@ "client": [ ], "mixins": [ + "AccessoriesNetworkingMixin" ], "injectors": { "defaultRequire": 1 diff --git a/gradle.properties b/gradle.properties index 6497f65c0..61e88dde1 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,5 @@ org.gradle.jvmargs=-Xmx4096M +org.gradle.java.home=C:/Program Files/Java/jdk-25.0.2 loom.ignoreDependencyLoomVersionValidation=true # New Data @@ -8,11 +9,11 @@ enabled_mixin_debugging_platforms=fabric # Adds renderdoc debugging run using owolib enabled_renderdoc_debugging_platforms=fabric # Adds test mod for designed platform -enabled_testmod_platforms=fabric,neoforge +enabled_testmod_platforms=fabric -enabled_platforms=fabric,neoforge +enabled_platforms=fabric -enabled_item_viewers=emi,rei,jei +enabled_item_viewers= # Types: none, rei, emi, jei selected_item_viewers=none diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 94113f200..19a6bdeb8 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.11-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.3.0-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/libs.versions.toml b/libs.versions.toml index 15127a458..04a1d9d61 100644 --- a/libs.versions.toml +++ b/libs.versions.toml @@ -1,47 +1,47 @@ # This file contains variours adjustable versioning used for depedencies for the given platforms using Version Catalog API in gradle [versions] -java = "21" +java = "25" -minecraft = "1.21.10" -minecraft_base = "1.21.10" +minecraft = "26.1" +minecraft_base = "26.1" -neoforge_minecraft_range = "[1.21.10,)" -fabric_minecraft_range = "~1.21.10" +neoforge_minecraft_range = "[26.1,)" +fabric_minecraft_range = "~26.1" # https://parchmentmc.org/docs/getting-started parchment = "2025.10.12" # Core Libs -fabric_loader = "0.17.2" # https://fabricmc.net/develop -fabric_api = "0.135.0+1.21.10" # https://fabricmc.net/develop +fabric_loader = "0.18.4" # https://fabricmc.net/develop +fabric_api = "0.144.3+26.1" # https://fabricmc.net/develop fabric_loader_range=">=0.16.9" fabric_api_range="*" -neoforge = "21.10.16-beta" # https://projects.neoforged.net/neoforged/neoforge +neoforge = "21.11.1-beta" # https://projects.neoforged.net/neoforged/neoforge ffapi_base = "0.4.42+d1308dedd1" -neoforge_range="[21.10.16-beta,)" +neoforge_range="[21.11.1-beta,)" neoforge_loader_range="[4,)" # Libs mixinextras = "0.5.0" -modmenu = "16.0.0-rc.1" # https://modrinth.com/mod/modmenu/versions +modmenu = "18.0.0-alpha.7" endec = "0.1.11" endec_netty = "0.1.5" endec_gson = "0.1.6" endec_jankson = "0.1.6" -owo_fabric = "0.12.24+1.21.9" -owo_neoforge = "0.12.27+1.21.10" +owo_fabric = "0.13.0+26.1" +owo_neoforge = "0.12.27+1.21.11" -owo_fabric_range = ">=0.12.24+1.21.9" -owo_neoforge_range = "[0.12.27+1.21.10,)" +owo_fabric_range = ">=0.13.0+26.1" +owo_neoforge_range = "[0.12.27+1.21.11,)" jankson = "1.2.2" @@ -61,7 +61,7 @@ item_viewer_type = "none" # Compat Mods -sodium="mc1.21.8-0.7.0" +sodium="mc26.1-0.8.7" geckolib_minecraft="1.21.8" geckolib="5.2.2" diff --git a/neoforge/src/main/java/io/wispforest/accessories/neoforge/AccessoriesForge.java b/neoforge/src/main/java/io/wispforest/accessories/neoforge/AccessoriesForge.java index 10a480069..367c95724 100644 --- a/neoforge/src/main/java/io/wispforest/accessories/neoforge/AccessoriesForge.java +++ b/neoforge/src/main/java/io/wispforest/accessories/neoforge/AccessoriesForge.java @@ -30,7 +30,7 @@ import net.minecraft.core.component.DataComponentType; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.core.registries.Registries; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.packs.PackType; import net.minecraft.server.packs.resources.ResourceManager; @@ -45,7 +45,7 @@ import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.GameRules; +import net.minecraft.world.level.gamerules.GameRules; import net.minecraft.world.level.storage.ValueInput; import net.minecraft.world.level.storage.ValueOutput; import net.neoforged.bus.api.EventPriority; @@ -187,7 +187,7 @@ public void registerStuff(RegisterEvent event){ event.register(Registries.DATA_COMPONENT_TYPE, (helper) -> AccessoriesDataComponents.init()); event.register(Registries.COMMAND_ARGUMENT_TYPE, (helper) -> CommandGenerators.registerAllArgumentTypes(new ArgumentRegistrationCallback() { @Override - public , T> RecordArgumentTypeInfo register(ResourceLocation location, Class clazz, RecordArgumentTypeInfo info) { + public , T> RecordArgumentTypeInfo register(Identifier location, Class clazz, RecordArgumentTypeInfo info) { helper.register(location, ArgumentTypeInfos.registerByClass(clazz, info)); return info; diff --git a/neoforge/src/main/java/io/wispforest/accessories/neoforge/AccessoriesNeoforgeInternals.java b/neoforge/src/main/java/io/wispforest/accessories/neoforge/AccessoriesNeoforgeInternals.java index 08edbded7..b3e161059 100644 --- a/neoforge/src/main/java/io/wispforest/accessories/neoforge/AccessoriesNeoforgeInternals.java +++ b/neoforge/src/main/java/io/wispforest/accessories/neoforge/AccessoriesNeoforgeInternals.java @@ -17,6 +17,7 @@ import io.wispforest.endec.format.bytebuf.ByteBufDeserializer; import io.wispforest.endec.format.bytebuf.ByteBufSerializer; import io.wispforest.owo.serialization.RegistriesAttribute; +import net.minecraft.Util; import net.minecraft.core.Holder; import net.minecraft.core.HolderLookup; import net.minecraft.core.Registry; @@ -24,7 +25,7 @@ import net.minecraft.network.RegistryFriendlyByteBuf; import net.minecraft.network.chat.Component; import net.minecraft.resources.RegistryOps; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.packs.PackType; @@ -32,6 +33,8 @@ import net.minecraft.server.packs.resources.SimplePreparableReloadListener; import net.minecraft.tags.TagKey; import net.minecraft.world.MenuProvider; +import net.minecraft.world.effect.MobEffect; +import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.ai.attributes.Attribute; import net.minecraft.world.entity.ai.attributes.AttributeModifier; @@ -44,6 +47,9 @@ import net.minecraft.world.item.TooltipFlag; import net.minecraft.world.item.component.TooltipDisplay; import net.minecraft.world.level.GameRules; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.material.Fluid; import net.neoforged.neoforge.common.NeoForge; import net.neoforged.neoforge.common.Tags; import net.neoforged.neoforge.common.conditions.ICondition; @@ -94,11 +100,11 @@ public void giveItemToPlayer(ServerPlayer player, ItemStack stack) { player.getInventory().placeItemBackInInventory(stack); } - public boolean isValidOnConditions(JsonObject object, String dataType, ResourceLocation key, SimplePreparableReloadListener listener, @Nullable RegistryOps.RegistryInfoLookup registryInfo) { + public boolean isValidOnConditions(JsonObject object, String dataType, Identifier key, SimplePreparableReloadListener listener, @Nullable RegistryOps.RegistryInfoLookup registryInfo) { return ICondition.conditionsMatched(((ContextAwareReloadListenerAccessor) listener).accessories$makeConditionalOps(), object); } - public MenuType registerMenuType(ResourceLocation location, Endec endec, TriFunction func) { + public MenuType registerMenuType(Identifier location, Endec endec, TriFunction func) { return Registry.register(BuiltInRegistries.MENU, location, IMenuTypeExtension.create((i, arg, arg2) -> { return func.apply(i, arg, endec.decodeFully(SerializationContext.attributes(RegistriesAttribute.of(arg2.registryAccess())), ByteBufDeserializer::of, arg2)); })); @@ -151,4 +157,19 @@ public void registerLoader(PackType type, IdentifiedResourceReloadListener loade public String getTagTranslation(TagKey tagKey) { return Tags.getTagTranslationKey(tagKey); } + + @Override + public String geEntryTranslation(Holder entry) { + var value = entry.value(); + + return switch (value) { + case Item item -> item.getDescriptionId(); + case Block block -> block.getDescriptionId(); + case EntityType type -> type.getDescriptionId(); + case MobEffect effect -> effect.getDescriptionId(); + case Attribute attribute -> attribute.getDescriptionId(); + case Fluid fluid -> fluid.getFluidType().getDescriptionId(); + default -> value.toString(); + }; + } } diff --git a/neoforge/src/main/java/io/wispforest/accessories/neoforge/client/AccessoriesClientForge.java b/neoforge/src/main/java/io/wispforest/accessories/neoforge/client/AccessoriesClientForge.java index a5d1ab0c1..f00fab6e6 100644 --- a/neoforge/src/main/java/io/wispforest/accessories/neoforge/client/AccessoriesClientForge.java +++ b/neoforge/src/main/java/io/wispforest/accessories/neoforge/client/AccessoriesClientForge.java @@ -90,23 +90,7 @@ public void initKeybindings(RegisterKeyMappingsEvent event) { } public static void clientTick(ClientTickEvent.Pre event) { - if (AccessoriesClient.OPEN_SCREEN.consumeClick()) { - var client = Minecraft.getInstance(); - var player = client.player; - - if (Accessories.config().screenOptions.prioritizeCreativeScreen() && player != null && player.isCreative()) { - if (client.gameMode.isServerControlledInventory()) { - player.sendOpenInventory(); - } else { - client.getTutorial().onOpenInventory(); - client.setScreen(new InventoryScreen(player)); - } - - return; - } - - AccessoriesClient.openScreenFromKey(); - } + AccessoriesClient.handleKeyMappings(Minecraft.getInstance()); } public static void itemTooltipCallback(ItemTooltipEvent event) { @@ -134,7 +118,7 @@ public void addRenderLayer(EntityRenderersEvent.AddLayers event) { } event.getSkins().stream() - .flatMap(type -> Stream.>of(event.getPlayerRenderer(type), event.getMannequinRenderer(type))) + .flatMap(type -> Stream.>of(event.getAvatarRenderer(type), event.getMannequinRenderer(type))) .filter(Objects::nonNull) .forEach(renderer -> renderer.addLayer(new AccessoriesRenderLayer<>(renderer))); } diff --git a/neoforge/src/main/java/io/wispforest/accessories/neoforge/mixin/client/AbstractContainerScreenMixin.java b/neoforge/src/main/java/io/wispforest/accessories/neoforge/mixin/client/AbstractContainerScreenMixin.java index f4783d568..41153f10e 100644 --- a/neoforge/src/main/java/io/wispforest/accessories/neoforge/mixin/client/AbstractContainerScreenMixin.java +++ b/neoforge/src/main/java/io/wispforest/accessories/neoforge/mixin/client/AbstractContainerScreenMixin.java @@ -38,6 +38,6 @@ public abstract class AbstractContainerScreenMixin implements ContainerScreenExt @WrapOperation(method = "keyPressed", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/KeyMapping;isActiveAndMatches(Lcom/mojang/blaze3d/platform/InputConstants$Key;)Z", ordinal = 0)) private boolean accessories$adjustCloseCheck(KeyMapping instance, InputConstants.Key key, Operation original) { - return original.call(instance, key) || original.call(AccessoriesClient.OPEN_SCREEN, key); + return original.call(instance, key) || AccessoriesClient.isInventoryKey(keyMapping -> original.call(keyMapping, key)); } } \ No newline at end of file diff --git a/neoforge/src/main/resources/interfaces.json b/neoforge/src/main/resources/interfaces.json index adea6e7d6..0dc914aa2 100644 --- a/neoforge/src/main/resources/interfaces.json +++ b/neoforge/src/main/resources/interfaces.json @@ -6,6 +6,6 @@ "io/wispforest/accessories/pond/AccessoriesRenderStateAPI" ], "net/minecraft/world/item/TooltipFlag": [ - "io/wispforest/accessories/pond/TooltipFlagExtension" + "io/wispforest/accessories/pond/TooltipFlagExtended" ] } \ No newline at end of file diff --git a/neoforge/src/testmod/java/io/wispforest/testccessories/neoforge/TestMenu.java b/neoforge/src/testmod/java/io/wispforest/testccessories/neoforge/TestMenu.java index c1d39067d..b4b2d0e4b 100644 --- a/neoforge/src/testmod/java/io/wispforest/testccessories/neoforge/TestMenu.java +++ b/neoforge/src/testmod/java/io/wispforest/testccessories/neoforge/TestMenu.java @@ -22,14 +22,13 @@ public TestMenu(int containerId, Inventory playerInventory) { var baseY = 20; - var generator = AccessoriesSlotGenerator.of(this::addSlot, 0, baseY, player, UniqueSlotTest.testSlot1Ref(), UniqueSlotTest.testSlot2Ref()); + var generator = AccessoriesSlotGenerator.of(this::addSlot, 0, baseY, player, UniqueSlotTest.testSlot1Ref(), UniqueSlotTest.testSlot2Ref(), UniqueSlotTest.testSlot3Ref()); baseY += 18; - if(generator != null) { - this.addedSlots = generator.padding(1) - .row(); - } + baseY += 4; + + if(generator != null) this.addedSlots = generator.row(); for(int i = 0; i < 3; ++i) { for(int j = 0; j < 9; ++j) { @@ -94,4 +93,4 @@ private boolean insertIntoSlotRange(ItemStack addition, int beginIndex, int endI private boolean insertIntoSlotRange(ItemStack addition, int beginIndex, int endIndex, boolean fromLast) { return this.moveItemStackTo(addition, beginIndex, endIndex, fromLast); } -} +} \ No newline at end of file diff --git a/neoforge/src/testmod/java/io/wispforest/testccessories/neoforge/Testccessories.java b/neoforge/src/testmod/java/io/wispforest/testccessories/neoforge/Testccessories.java index a936f2d8d..15779b3e1 100644 --- a/neoforge/src/testmod/java/io/wispforest/testccessories/neoforge/Testccessories.java +++ b/neoforge/src/testmod/java/io/wispforest/testccessories/neoforge/Testccessories.java @@ -6,7 +6,7 @@ import io.wispforest.testccessories.neoforge.accessories.*; import io.wispforest.testccessories.neoforge.client.TestScreenPacket; import net.minecraft.core.registries.Registries; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.world.flag.FeatureFlags; import net.minecraft.world.inventory.MenuType; import net.neoforged.bus.api.IEventBus; @@ -54,11 +54,11 @@ public static void onInitialize(FMLCommonSetupEvent event){ UniqueSlotHandling.EVENT.register(UniqueSlotTest.INSTANCE); } - public static ResourceLocation of(String path) { - return ResourceLocation.fromNamespaceAndPath(MODID, path); + public static Identifier of(String path) { + return Identifier.fromNamespaceAndPath(MODID, path); } public static void initNetworkPackets() { - AccessoriesNetworking.CHANNEL.registerClientboundDeferred(TestScreenPacket.class, TestScreenPacket.ENDEC); + AccessoriesNetworking.CHANNEL.registerServerbound(TestScreenPacket.class, TestScreenPacket.ENDEC, AccessoriesNetworking.serverHandler(TestScreenPacket::handlePacket)); } } \ No newline at end of file diff --git a/neoforge/src/testmod/java/io/wispforest/testccessories/neoforge/UniqueSlotTest.java b/neoforge/src/testmod/java/io/wispforest/testccessories/neoforge/UniqueSlotTest.java index 3fd4e9be6..11e6b7a72 100644 --- a/neoforge/src/testmod/java/io/wispforest/testccessories/neoforge/UniqueSlotTest.java +++ b/neoforge/src/testmod/java/io/wispforest/testccessories/neoforge/UniqueSlotTest.java @@ -1,11 +1,12 @@ package io.wispforest.testccessories.neoforge; -import io.wispforest.accessories.api.slot.SlotBasedPredicate; -import io.wispforest.accessories.api.slot.SlotPredicateRegistry; +import io.wispforest.accessories.api.action.ActionResponse; import io.wispforest.accessories.api.slot.SlotTypeReference; import io.wispforest.accessories.api.slot.UniqueSlotHandling; -import net.fabricmc.fabric.api.util.TriState; -import net.minecraft.resources.ResourceLocation; +import io.wispforest.accessories.api.slot.validator.SlotValidator; +import io.wispforest.accessories.api.slot.validator.SlotValidatorRegistry; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.Identifier; import net.minecraft.tags.BlockTags; import net.minecraft.world.entity.EntityType; import net.minecraft.world.item.BlockItem; @@ -13,17 +14,19 @@ public class UniqueSlotTest implements UniqueSlotHandling.RegistrationCallback { - private final ResourceLocation slotPredicate1 = Testccessories.of("test_slot_1_equipment"); - private final ResourceLocation slotPredicate2 = Testccessories.of("test_slot_2_equipment"); - private final ResourceLocation slotPredicate3 = Testccessories.of("test_slot_3_equipment"); + private final Identifier slotPredicate1 = Testccessories.of("test_slot_1_equipment"); + private final Identifier slotPredicate2 = Testccessories.of("test_slot_2_equipment"); + private final Identifier slotPredicate3 = Testccessories.of("test_slot_3_equipment"); public static final UniqueSlotTest INSTANCE = new UniqueSlotTest(); private UniqueSlotTest(){ - SlotPredicateRegistry.register(slotPredicate1, SlotBasedPredicate.ofItem(item -> item.equals(TestItems.testItem1))); - SlotPredicateRegistry.register(slotPredicate2, SlotBasedPredicate.ofItem(item -> item.equals(TestItems.testItem2))); - SlotPredicateRegistry.register(slotPredicate3, (level, slotType, slot, stack) -> { - return (stack.getItem() instanceof BlockItem blockItem && blockItem.getBlock().builtInRegistryHolder().is(BlockTags.BEDS)) ? TriState.TRUE : TriState.DEFAULT; + SlotValidatorRegistry.register(slotPredicate1, SlotValidator.ofItem(item -> item.equals(TestItems.testItem1))); + SlotValidatorRegistry.register(slotPredicate2, SlotValidator.ofItem(item -> item.equals(TestItems.testItem2))); + SlotValidatorRegistry.register(slotPredicate3, (level, slotType, slot, stack, buffer) -> { + if (stack.getItem() instanceof BlockItem blockItem && blockItem.getBlock().builtInRegistryHolder().is(BlockTags.BEDS)) { + buffer.respondWith(ActionResponse.of(true, Component.literal("The bed fits within the bed slot!"))); + } }); } diff --git a/neoforge/src/testmod/java/io/wispforest/testccessories/neoforge/accessories/PointedDripstoneAccessory.java b/neoforge/src/testmod/java/io/wispforest/testccessories/neoforge/accessories/PointedDripstoneAccessory.java index 73f8571c9..a100d6d54 100644 --- a/neoforge/src/testmod/java/io/wispforest/testccessories/neoforge/accessories/PointedDripstoneAccessory.java +++ b/neoforge/src/testmod/java/io/wispforest/testccessories/neoforge/accessories/PointedDripstoneAccessory.java @@ -21,7 +21,7 @@ import net.minecraft.client.renderer.entity.state.LivingEntityRenderState; import net.minecraft.client.renderer.item.ItemStackRenderState; import net.minecraft.client.renderer.texture.OverlayTexture; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.world.entity.HumanoidArm; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.ai.attributes.AttributeModifier; @@ -31,7 +31,7 @@ public class PointedDripstoneAccessory implements Accessory { - private static final ResourceLocation ATTACK_DAMAGE_LOCATION = Testccessories.of("pointed_dripstone_accessory_attack_damage"); + private static final Identifier ATTACK_DAMAGE_LOCATION = Testccessories.of("pointed_dripstone_accessory_attack_damage"); public static void clientInit() { AccessoriesRendererRegistry.bindItemToRenderer(Items.POINTED_DRIPSTONE, Testccessories.of("dripped_gloves"), Renderer::new); diff --git a/neoforge/src/testmod/java/io/wispforest/testccessories/neoforge/accessories/RingIncreaserAccessory.java b/neoforge/src/testmod/java/io/wispforest/testccessories/neoforge/accessories/RingIncreaserAccessory.java index acd789ef0..4c118bc42 100644 --- a/neoforge/src/testmod/java/io/wispforest/testccessories/neoforge/accessories/RingIncreaserAccessory.java +++ b/neoforge/src/testmod/java/io/wispforest/testccessories/neoforge/accessories/RingIncreaserAccessory.java @@ -6,7 +6,7 @@ import io.wispforest.accessories.api.slot.SlotReference; import io.wispforest.testccessories.neoforge.Testccessories; import net.minecraft.core.component.DataComponents; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.world.entity.ai.attributes.AttributeModifier; import net.minecraft.world.item.DyeColor; import net.minecraft.world.item.ItemStack; @@ -18,7 +18,7 @@ public static void init(){ AccessoryRegistry.register(Items.BEACON, new RingIncreaserAccessory()); } - private static final ResourceLocation ringAdditionLocation = Testccessories.of("additional_rings"); + private static final Identifier ringAdditionLocation = Testccessories.of("additional_rings"); @Override public void onEquip(ItemStack stack, SlotReference reference) { diff --git a/neoforge/src/testmod/java/io/wispforest/testccessories/neoforge/accessories/WaterBreathingAccessory.java b/neoforge/src/testmod/java/io/wispforest/testccessories/neoforge/accessories/WaterBreathingAccessory.java index 08b5d3beb..3e7ffb931 100644 --- a/neoforge/src/testmod/java/io/wispforest/testccessories/neoforge/accessories/WaterBreathingAccessory.java +++ b/neoforge/src/testmod/java/io/wispforest/testccessories/neoforge/accessories/WaterBreathingAccessory.java @@ -7,7 +7,7 @@ import io.wispforest.testccessories.neoforge.TestItems; import io.wispforest.testccessories.neoforge.Testccessories; import net.minecraft.core.component.DataComponents; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.ai.attributes.AttributeModifier; import net.minecraft.world.entity.ai.attributes.Attributes; @@ -16,7 +16,7 @@ public class WaterBreathingAccessory implements Accessory { - private static final ResourceLocation GRAVITY_LOCATION = Testccessories.of("gravity_accessory_adjustment"); + private static final Identifier GRAVITY_LOCATION = Testccessories.of("gravity_accessory_adjustment"); public static void init() { AccessoryRegistry.register(TestItems.testItem1.get(), new WaterBreathingAccessory()); diff --git a/neoforge/src/testmod/java/io/wispforest/testccessories/neoforge/client/TestScreen.java b/neoforge/src/testmod/java/io/wispforest/testccessories/neoforge/client/TestScreen.java index 3b705ecc8..e8d1920a5 100644 --- a/neoforge/src/testmod/java/io/wispforest/testccessories/neoforge/client/TestScreen.java +++ b/neoforge/src/testmod/java/io/wispforest/testccessories/neoforge/client/TestScreen.java @@ -9,7 +9,7 @@ import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; import net.minecraft.client.gui.screens.inventory.MenuAccess; import net.minecraft.network.chat.Component; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.Identifier; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.inventory.Slot; @@ -17,12 +17,15 @@ public class TestScreen extends AbstractContainerScreen implements MenuAccess { - private static final ResourceLocation SLOT_FRAME = Accessories.of("textures/gui/slot.png"); + private static final ResourceLocation SLOT_FRAME = Accessories.of("textures/gui/theme/light/slot.png"); - private static final ResourceLocation BACKGROUND_PATCH = Accessories.of("background_patch"); + private static final Identifier BACKGROUND_PATCH = Accessories.of("background_patch"); public TestScreen(TestMenu menu, Inventory playerInventory, Component title) { super(menu, playerInventory, title); + + inventoryLabelY = 42069; + titleLabelX -= 10; } @Override @@ -43,13 +46,15 @@ protected void renderBg(GuiGraphics guiGraphics, float partialTick, int mouseX, } } - var padding = 4; + var titleOffset = 12; + + var padding = 6; var width = (maxX - minX) + 18 + (padding * 2); - var height = (maxY - minY) + 18 + (padding * 2); + var height = (maxY - minY) + 18 + (padding * 2) + titleOffset; var startX = minX - padding; - var startY = minY - padding; + var startY = minY - titleOffset - padding; guiGraphics.push().translate((float)leftPos, (float)topPos); diff --git a/neoforge/src/testmod/java/io/wispforest/testccessories/neoforge/mixin/AccessoriesNetworkingMixin.java b/neoforge/src/testmod/java/io/wispforest/testccessories/neoforge/mixin/AccessoriesNetworkingMixin.java index 579cd133a..c8ef64da4 100644 --- a/neoforge/src/testmod/java/io/wispforest/testccessories/neoforge/mixin/AccessoriesNetworkingMixin.java +++ b/neoforge/src/testmod/java/io/wispforest/testccessories/neoforge/mixin/AccessoriesNetworkingMixin.java @@ -13,4 +13,4 @@ public abstract class AccessoriesNetworkingMixin { private static void registerOtherPackets(CallbackInfo ci) { Testccessories.initNetworkPackets(); } -} +} \ No newline at end of file diff --git a/neoforge/src/testmod/resources/data/testccessories/accessories/entity/test_slots.json b/neoforge/src/testmod/resources/data/testccessories/accessories/entity/test_slots.json new file mode 100644 index 000000000..20d6d3a53 --- /dev/null +++ b/neoforge/src/testmod/resources/data/testccessories/accessories/entity/test_slots.json @@ -0,0 +1,9 @@ +{ + "replace": false, + "entities": [ + "#accessories:defaulted_targets" + ], + "slots": [ + "something" + ] +} \ No newline at end of file diff --git a/neoforge/src/testmod/resources/data/testccessories/accessories/slot/anklet.json b/neoforge/src/testmod/resources/data/testccessories/accessories/slot/anklet.json new file mode 100644 index 000000000..289267b46 --- /dev/null +++ b/neoforge/src/testmod/resources/data/testccessories/accessories/slot/anklet.json @@ -0,0 +1,5 @@ +{ + "replace": false, + "amount": 3, + "operation": "set" +} \ No newline at end of file diff --git a/neoforge/src/testmod/resources/data/testccessories/accessories/slot/back.json b/neoforge/src/testmod/resources/data/testccessories/accessories/slot/back.json new file mode 100644 index 000000000..d3e6b197e --- /dev/null +++ b/neoforge/src/testmod/resources/data/testccessories/accessories/slot/back.json @@ -0,0 +1,5 @@ +{ + "replace": false, + "amount": 1, + "operation": "add" +} \ No newline at end of file diff --git a/neoforge/src/testmod/resources/data/testccessories/accessories/slot/something.json b/neoforge/src/testmod/resources/data/testccessories/accessories/slot/something.json new file mode 100644 index 000000000..a12ce2de4 --- /dev/null +++ b/neoforge/src/testmod/resources/data/testccessories/accessories/slot/something.json @@ -0,0 +1,6 @@ +{ + "order": 100, + "icon": "accessories:gui/slot/charm", + "amount": 0, + "operation": "SET" +} \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index 80bbf3d5f..8c7ed56ca 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -19,6 +19,6 @@ dependencyResolutionManagement { include("common") include("fabric") -include("neoforge") +//include("neoforge") // Disabled - no owo-lib-neoforge for 1.21.11 rootProject.name = "accessories" \ No newline at end of file