From 340c8915967236d171a3302a14cc59a5a5b175ef Mon Sep 17 00:00:00 2001 From: RedstoneWizard08 Date: Sun, 15 Sep 2024 20:33:48 -0700 Subject: [PATCH 01/11] [feat] Initial work on weapon leveling & item attributes --- build.gradle | 206 +++++++++--------- gradle.properties | 1 + .../playerex/mixin/ItemStackMixin.java | 87 ++++++-- .../bibireden/playerex/api/PlayerEXTags.kt | 5 +- .../api/attribute/PlayerEXAttributes.kt | 3 + .../playerex/api/items/ItemWithAttributes.kt | 8 + .../playerex/api/items/WeaponItem.kt | 25 +++ .../playerex/config/PlayerEXConfigModel.kt | 10 + .../data/playerex/tags/items/weapons.json | 8 + 9 files changed, 234 insertions(+), 119 deletions(-) create mode 100644 src/main/kotlin/com/bibireden/playerex/api/items/ItemWithAttributes.kt create mode 100644 src/main/kotlin/com/bibireden/playerex/api/items/WeaponItem.kt create mode 100644 src/main/resources/data/playerex/tags/items/weapons.json diff --git a/build.gradle b/build.gradle index 57cf8252..e8e9efc5 100644 --- a/build.gradle +++ b/build.gradle @@ -1,154 +1,160 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { - id 'fabric-loom' version "1.7-SNAPSHOT" - id 'maven-publish' - id "org.jetbrains.kotlin.jvm" version "2.0.0" - id 'org.jetbrains.kotlin.plugin.serialization' version '2.0.0' - id("com.google.devtools.ksp") version "2.0.0-1.0.21" + id 'fabric-loom' version "1.7-SNAPSHOT" + id 'maven-publish' + id "org.jetbrains.kotlin.jvm" version "2.0.0" + id 'org.jetbrains.kotlin.plugin.serialization' version '2.0.0' + id("com.google.devtools.ksp") version "2.0.0-1.0.21" } version = project.mod_version group = project.maven_group base { - archivesName = project.archives_base_name + archivesName = project.archives_base_name } repositories { - maven { - name = "wispForestReleases" - url = uri("https://maven.wispforest.io/releases") - } - maven { - name = "Ladysnake Mods" - url = 'https://maven.ladysnake.org/releases' - } - maven { - name = "Modrinth" - url = "https://api.modrinth.com/maven" - } - maven { - name = "Nucleoid" - url = "https://maven.nucleoid.xyz/" - } - maven { - url = "https://maven.kosmx.dev/" - } - maven { - name = 'ParchmentMC' - url = 'https://maven.parchmentmc.org' - } - maven { - name = 'Quilt' - url = "https://maven.quiltmc.org/repository/release/" - } + maven { + name = "wispForestReleases" + url = uri("https://maven.wispforest.io/releases") + } + maven { + name = "Ladysnake Mods" + url = 'https://maven.ladysnake.org/releases' + } + maven { + name = "Modrinth" + url = "https://api.modrinth.com/maven" + } + maven { + name = "Nucleoid" + url = "https://maven.nucleoid.xyz/" + } + maven { + url = "https://maven.kosmx.dev/" + } + maven { + name = 'ParchmentMC' + url = 'https://maven.parchmentmc.org' + } + maven { + name = 'Quilt' + url = "https://maven.quiltmc.org/repository/release/" + } + maven { + name = "Terraformers" + url = "https://maven.terraformersmc.com/" + } } loom { splitEnvironmentSourceSets() - mods { - "playerex-directors-cut" { - sourceSet sourceSets.main - sourceSet sourceSets.client - } - } + mods { + "playerex-directors-cut" { + sourceSet sourceSets.main + sourceSet sourceSets.client + } + } } dependencies { - minecraft "com.mojang:minecraft:${project.minecraft_version}" + minecraft "com.mojang:minecraft:${project.minecraft_version}" - mappings loom.layered() { - mappings("org.quiltmc:quilt-mappings:${project.minecraft_version}+build.${project.quilt_mappings_version}:intermediary-v2") - officialMojangMappings() - parchment("org.parchmentmc.data:parchment-${project.parchment_version}@zip") - } + mappings loom.layered() { + mappings("org.quiltmc:quilt-mappings:${project.minecraft_version}+build.${project.quilt_mappings_version}:intermediary-v2") + officialMojangMappings() + parchment("org.parchmentmc.data:parchment-${project.parchment_version}@zip") + } - modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" + modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" - modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" - modImplementation "net.fabricmc:fabric-language-kotlin:${project.fabric_kotlin_version}" + modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" + modImplementation "net.fabricmc:fabric-language-kotlin:${project.fabric_kotlin_version}" - // in-house - modImplementation("maven.modrinth:data-attributes-directors-cut:${project.data_attributes_version}") - modImplementation include("maven.modrinth:opc-directors-cut:${project.opc_version}") + // in-house + modImplementation("maven.modrinth:data-attributes-directors-cut:${project.data_attributes_version}") + modImplementation include("maven.modrinth:opc-directors-cut:${project.opc_version}") - // Cardinal Components - modImplementation include("dev.onyxstudios.cardinal-components-api:cardinal-components-base:${project.cardinal_components_version}") - modImplementation include("dev.onyxstudios.cardinal-components-api:cardinal-components-entity:${project.cardinal_components_version}") - modImplementation include("dev.onyxstudios.cardinal-components-api:cardinal-components-chunk:${project.cardinal_components_version}") - modImplementation include("dev.onyxstudios.cardinal-components-api:cardinal-components-level:${project.cardinal_components_version}") + // Cardinal Components + modImplementation include("dev.onyxstudios.cardinal-components-api:cardinal-components-base:${project.cardinal_components_version}") + modImplementation include("dev.onyxstudios.cardinal-components-api:cardinal-components-entity:${project.cardinal_components_version}") + modImplementation include("dev.onyxstudios.cardinal-components-api:cardinal-components-chunk:${project.cardinal_components_version}") + modImplementation include("dev.onyxstudios.cardinal-components-api:cardinal-components-level:${project.cardinal_components_version}") - modImplementation include("maven.modrinth:AdditionalEntityAttributes:${project.additional_entity_attributes_version}") - modImplementation("maven.modrinth:ranged-weapon-api:${project.ranged_weapon_api_version}") + modImplementation include("maven.modrinth:AdditionalEntityAttributes:${project.additional_entity_attributes_version}") + modImplementation("maven.modrinth:ranged-weapon-api:${project.ranged_weapon_api_version}") - modImplementation include("io.wispforest:endec:${project.endec_version}") - modImplementation include("io.wispforest.endec:gson:${project.endec_gson_version}") - modImplementation include("io.wispforest.endec:netty:${project.endec_netty_version}") + modImplementation include("io.wispforest:endec:${project.endec_version}") + modImplementation include("io.wispforest.endec:gson:${project.endec_gson_version}") + modImplementation include("io.wispforest.endec:netty:${project.endec_netty_version}") - // owo - annotationProcessor modImplementation("io.wispforest:owo-lib:${project.owo_version}") - include "io.wispforest:owo-sentinel:${project.owo_version}" + // owo + annotationProcessor modImplementation("io.wispforest:owo-lib:${project.owo_version}") + include "io.wispforest:owo-sentinel:${project.owo_version}" - implementation("com.google.devtools.ksp:symbol-processing-api:${project.ksp_version}") - implementation("com.squareup:kotlinpoet-ksp:${project.kotlinpoet_version}") - ksp("dev.kosmx.kowoconfig:ksp-owo-config:${project.ksp_owo_config_version}") + implementation("com.google.devtools.ksp:symbol-processing-api:${project.ksp_version}") + implementation("com.squareup:kotlinpoet-ksp:${project.kotlinpoet_version}") + ksp("dev.kosmx.kowoconfig:ksp-owo-config:${project.ksp_owo_config_version}") - modImplementation include("eu.pb4:placeholder-api:${project.placeholder_api_version}") + modImplementation include("eu.pb4:placeholder-api:${project.placeholder_api_version}") - implementation include("net.objecthunter:exp4j:${project.exp4j_version}") + implementation include("net.objecthunter:exp4j:${project.exp4j_version}") - include(implementation(annotationProcessor("io.github.llamalad7:mixinextras-fabric:${project.mixinextras_version}"))) + modRuntimeOnly "com.terraformersmc:modmenu:${project.modmenu_version}" + + include(implementation(annotationProcessor("io.github.llamalad7:mixinextras-fabric:${project.mixinextras_version}"))) } processResources { - inputs.property "version", project.version + inputs.property "version", project.version - filesMatching("fabric.mod.json") { - expand "version": project.version - } + filesMatching("fabric.mod.json") { + expand "version": project.version + } } tasks.withType(JavaCompile).configureEach { - it.options.release = 17 + it.options.release = 17 } tasks.withType(KotlinCompile).configureEach { - kotlinOptions { - jvmTarget = 17 - } + kotlinOptions { + jvmTarget = 17 + } } java { - // Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task - // if it is present. - // If you remove this line, sources will not be generated. - withSourcesJar() + // Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task + // if it is present. + // If you remove this line, sources will not be generated. + withSourcesJar() - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 } jar { - from("LICENSE") { - rename { "${it}_${project.base.archivesName.get()}"} - } + from("LICENSE") { + rename { "${it}_${project.base.archivesName.get()}" } + } } // configure the maven publication publishing { - publications { - mavenJava(MavenPublication) { - from components.java - } - } - - // See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing. - repositories { - // Add repositories to publish to here. - // Notice: This block does NOT have the same function as the block in the top level. - // The repositories here will be used for publishing your artifact, not for - // retrieving dependencies. - } + publications { + mavenJava(MavenPublication) { + from components.java + } + } + + // See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing. + repositories { + // Add repositories to publish to here. + // Notice: This block does NOT have the same function as the block in the top level. + // The repositories here will be used for publishing your artifact, not for + // retrieving dependencies. + } } \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index bc08cfa9..ad802984 100644 --- a/gradle.properties +++ b/gradle.properties @@ -42,5 +42,6 @@ endec_gson_version=0.1.4 endec_netty_version=0.1.3 exp4j_version=0.4.8 +modmenu_version=7.2.2 mixinextras_version=0.4.0 diff --git a/src/main/java/com/bibireden/playerex/mixin/ItemStackMixin.java b/src/main/java/com/bibireden/playerex/mixin/ItemStackMixin.java index 280fe69c..26b3a178 100644 --- a/src/main/java/com/bibireden/playerex/mixin/ItemStackMixin.java +++ b/src/main/java/com/bibireden/playerex/mixin/ItemStackMixin.java @@ -1,13 +1,18 @@ package com.bibireden.playerex.mixin; import com.bibireden.data_attributes.api.item.ItemFields; +import com.bibireden.data_attributes.endec.nbt.NbtDeserializer; +import com.bibireden.data_attributes.endec.nbt.NbtSerializer; import com.bibireden.playerex.PlayerEX; import com.bibireden.playerex.api.PlayerEXTags; +import com.bibireden.playerex.api.items.ItemWithAttributes; +import com.bibireden.playerex.api.items.WeaponItem; import com.bibireden.playerex.config.PlayerEXConfigModel; import com.bibireden.playerex.util.PlayerEXUtil; import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; import com.llamalad7.mixinextras.sugar.Local; +import io.wispforest.endec.Endec; import net.minecraft.ChatFormatting; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; @@ -19,15 +24,13 @@ import net.minecraft.world.InteractionResultHolder; import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.ai.attributes.Attribute; -import net.minecraft.world.entity.ai.attributes.AttributeInstance; -import net.minecraft.world.entity.ai.attributes.AttributeModifier; -import net.minecraft.world.entity.ai.attributes.Attributes; +import net.minecraft.world.entity.ai.attributes.*; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.TooltipFlag; import net.minecraft.world.item.context.UseOnContext; import net.minecraft.world.level.Level; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -39,22 +42,31 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.asm.mixin.injection.callback.LocalCapture; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.UUID; +import java.util.*; import java.util.function.Consumer; @Mixin(ItemStack.class) -abstract class ItemStackMixin { +abstract class ItemStackMixin implements WeaponItem, ItemWithAttributes { + @Unique + private static final Endec> ATTRIBUTES_CODEC = Endec.DOUBLE.mapOf().xmap(HashMap::new, Map::copyOf); + + @Unique + private static final String ATTRIBUTES_KEY = "playerex$attributes"; + + @Unique + private HashMap playerex$attributes; + @Shadow public abstract boolean hurt(int amount, RandomSource random, @Nullable ServerPlayer serverPlayer); + @Shadow + public abstract CompoundTag getOrCreateTag(); + @Inject(method = "use(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/entity/player/Player;Lnet/minecraft/world/InteractionHand;)Lnet/minecraft/world/InteractionResultHolder;", at = @At(value = "HEAD"), cancellable = true) public void preventUse(Level level, Player player, InteractionHand usedHand, CallbackInfoReturnable> cir) { if (!PlayerEX.CONFIG.getItemBreakingEnabled()) return; - ItemStack stack = (ItemStack)(Object)this; + ItemStack stack = (ItemStack) (Object) this; if (PlayerEXUtil.isBroken(stack)) { cir.setReturnValue(InteractionResultHolder.fail(stack)); } @@ -64,7 +76,7 @@ public void preventUse(Level level, Player player, InteractionHand usedHand, Cal public void preventUseOnBlock(UseOnContext context, CallbackInfoReturnable cir) { if (!PlayerEX.CONFIG.getItemBreakingEnabled()) return; - ItemStack stack = (ItemStack)(Object)this; + ItemStack stack = (ItemStack) (Object) this; if (PlayerEXUtil.isBroken(stack)) { cir.setReturnValue(InteractionResult.FAIL); } @@ -74,7 +86,7 @@ public void preventUseOnBlock(UseOnContext context, CallbackInfoReturnable cir) { if (!PlayerEX.CONFIG.getItemBreakingEnabled()) return; - ItemStack stack = (ItemStack)(Object)this; + ItemStack stack = (ItemStack) (Object) this; if (PlayerEXUtil.isBroken(stack)) { cir.setReturnValue(true); } @@ -84,10 +96,11 @@ public void preventDamage(int amount, RandomSource random, ServerPlayer user, Ca public void preventBreak(int amount, T entity, Consumer onBroken, CallbackInfo ci) { if (!PlayerEX.CONFIG.getItemBreakingEnabled()) return; - ItemStack stack = (ItemStack)(Object)this; - if (stack.getItem().builtInRegistryHolder().is(PlayerEXTags.UNBREAKABLE_ITEMS)) { + ItemStack stack = (ItemStack) (Object) this; + if (stack.getItemHolder().is(PlayerEXTags.UNBREAKABLE_ITEMS)) { if (!PlayerEXUtil.isBroken(stack)) { CompoundTag tag = stack.getTag(); + assert tag != null; tag.putBoolean("broken", true); stack.setTag(tag); } @@ -99,9 +112,10 @@ public void preventBreak(int amount, T entity, Consumer public void removeBrokenOnRepair(int damage, CallbackInfo ci) { if (!PlayerEX.CONFIG.getItemBreakingEnabled()) return; - ItemStack stack = (ItemStack)(Object)this; + ItemStack stack = (ItemStack) (Object) this; if (PlayerEXUtil.isBroken(stack) && damage < stack.getDamageValue()) { CompoundTag tag = stack.getTag(); + assert tag != null; tag.putBoolean("broken", false); stack.setTag(tag); } @@ -111,7 +125,7 @@ public void removeBrokenOnRepair(int damage, CallbackInfo ci) { public void preventArmour(EquipmentSlot slot, CallbackInfoReturnable> cir) { if (!PlayerEX.CONFIG.getItemBreakingEnabled()) return; - ItemStack stack = (ItemStack)(Object)this; + ItemStack stack = (ItemStack) (Object) this; HashMultimap hashmap = HashMultimap.create(cir.getReturnValue()); if (PlayerEXUtil.isBroken(stack)) { PlayerEXUtil.removeModifier(hashmap, Attributes.ARMOR); @@ -142,7 +156,8 @@ public void preventArmour(EquipmentSlot slot, CallbackInfoReturnable entry, AttributeModifier modifier) { - if (modifier.getOperation() != AttributeModifier.Operation.ADDITION) return ItemStack.ATTRIBUTE_MODIFIER_FORMAT.format(e); + if (modifier.getOperation() != AttributeModifier.Operation.ADDITION) + return ItemStack.ATTRIBUTE_MODIFIER_FORMAT.format(e); return ItemStack.ATTRIBUTE_MODIFIER_FORMAT.format(e); } @@ -167,7 +182,9 @@ public void preventArmour(EquipmentSlot slot, CallbackInfoReturnable cir) { + compoundTag.put(ATTRIBUTES_KEY, ATTRIBUTES_CODEC.encodeFully(NbtSerializer::of, playerex$attributes)); + } + + @SuppressWarnings("AddedMixinMembersNamePattern") + @Override + public double getAttributeValue(@NotNull RangedAttribute attr) { + if (playerex$attributes == null) { + CompoundTag tag = getOrCreateTag(); + playerex$attributes = tag.contains(ATTRIBUTES_KEY) ? ATTRIBUTES_CODEC.decodeFully(NbtDeserializer::of, tag.get(ATTRIBUTES_KEY)) : new HashMap<>(); + } + + return playerex$attributes.computeIfAbsent(attr.getDescriptionId(), s -> attr.getDefaultValue()); + } + + @SuppressWarnings("AddedMixinMembersNamePattern") + @Override + public void setAttributeValue(@NotNull RangedAttribute attr, double value) { + if (playerex$attributes == null) { + CompoundTag tag = getOrCreateTag(); + playerex$attributes = tag.contains(ATTRIBUTES_KEY) ? ATTRIBUTES_CODEC.decodeFully(NbtDeserializer::of, tag.get(ATTRIBUTES_KEY)) : new HashMap<>(); + } + + playerex$attributes.put(attr.getDescriptionId(), value); + } } diff --git a/src/main/kotlin/com/bibireden/playerex/api/PlayerEXTags.kt b/src/main/kotlin/com/bibireden/playerex/api/PlayerEXTags.kt index 1742af33..0ec11b76 100644 --- a/src/main/kotlin/com/bibireden/playerex/api/PlayerEXTags.kt +++ b/src/main/kotlin/com/bibireden/playerex/api/PlayerEXTags.kt @@ -8,4 +8,7 @@ import net.minecraft.world.item.Item object PlayerEXTags { @JvmField val UNBREAKABLE_ITEMS: TagKey = TagKey.create(Registries.ITEM, PlayerEX.id("unbreakable")) -} \ No newline at end of file + + @JvmField + val WEAPONS: TagKey = TagKey.create(Registries.ITEM, PlayerEX.id("weapons")) +} diff --git a/src/main/kotlin/com/bibireden/playerex/api/attribute/PlayerEXAttributes.kt b/src/main/kotlin/com/bibireden/playerex/api/attribute/PlayerEXAttributes.kt index 8c7415d6..d8313da8 100644 --- a/src/main/kotlin/com/bibireden/playerex/api/attribute/PlayerEXAttributes.kt +++ b/src/main/kotlin/com/bibireden/playerex/api/attribute/PlayerEXAttributes.kt @@ -75,6 +75,9 @@ object PlayerEXAttributes { @JvmField val RANGED_CRITICAL_DAMAGE = register("ranged_crit_damage", 0.0, 0.0, 1_000_000.0) + @JvmField + val EXPERIENCE = register("experience", 0.0, 0.0, 1_000_000_000_000.0) + @ApiStatus.Internal fun register(path: String, base: Double, min: Double, max: Double): RangedAttribute { val attribute = RangedAttribute("attribute.name.${PlayerEX.MOD_ID}.$path", base, min, max) diff --git a/src/main/kotlin/com/bibireden/playerex/api/items/ItemWithAttributes.kt b/src/main/kotlin/com/bibireden/playerex/api/items/ItemWithAttributes.kt new file mode 100644 index 00000000..c862dee2 --- /dev/null +++ b/src/main/kotlin/com/bibireden/playerex/api/items/ItemWithAttributes.kt @@ -0,0 +1,8 @@ +package com.bibireden.playerex.api.items + +import net.minecraft.world.entity.ai.attributes.RangedAttribute + +interface ItemWithAttributes { + fun getAttributeValue(attr: RangedAttribute): Double + fun setAttributeValue(attr: RangedAttribute, value: Double) +} diff --git a/src/main/kotlin/com/bibireden/playerex/api/items/WeaponItem.kt b/src/main/kotlin/com/bibireden/playerex/api/items/WeaponItem.kt new file mode 100644 index 00000000..4106fd5a --- /dev/null +++ b/src/main/kotlin/com/bibireden/playerex/api/items/WeaponItem.kt @@ -0,0 +1,25 @@ +package com.bibireden.playerex.api.items + +import com.bibireden.playerex.api.attribute.PlayerEXAttributes.EXPERIENCE + +interface WeaponItem { + fun isWeapon(): Boolean + + var xp: Double + get() { + val self = this as ItemWithAttributes + + return self.getAttributeValue(EXPERIENCE) + } + set(value) { + val self = this as ItemWithAttributes + + self.setAttributeValue(EXPERIENCE, value) + } + + companion object { + fun getExpReq(level: Int): Double { + return (1.0 / 100.0) * (level * level) + 50.0 + } + } +} diff --git a/src/main/kotlin/com/bibireden/playerex/config/PlayerEXConfigModel.kt b/src/main/kotlin/com/bibireden/playerex/config/PlayerEXConfigModel.kt index d6254169..fff5993b 100644 --- a/src/main/kotlin/com/bibireden/playerex/config/PlayerEXConfigModel.kt +++ b/src/main/kotlin/com/bibireden/playerex/config/PlayerEXConfigModel.kt @@ -84,5 +84,15 @@ class PlayerEXConfigModel { @JvmField var expNegationFactor: Int = 95 + data class WeaponLevelingSettings( + @JvmField + var maxLevel: Int = 500, + + @JvmField + var damagePerLevel: Double = 0.1, + ) + + @JvmField @Nest var weaponLevelingSettings = WeaponLevelingSettings() + enum class Tooltip { Default, Vanilla, PlayerEX } } \ No newline at end of file diff --git a/src/main/resources/data/playerex/tags/items/weapons.json b/src/main/resources/data/playerex/tags/items/weapons.json new file mode 100644 index 00000000..cd948b27 --- /dev/null +++ b/src/main/resources/data/playerex/tags/items/weapons.json @@ -0,0 +1,8 @@ +{ + "values": [ + "#minecraft:swords", + "#minecraft:axes", + "minecraft:bow", + "minecraft:trident" + ] +} From 7f85b685c5d0993e5fb3b0dcda81e34e16092f3e Mon Sep 17 00:00:00 2001 From: naomi Date: Mon, 16 Sep 2024 15:32:47 +0100 Subject: [PATCH 02/11] Revert some changes - Revert build.gradle - Revert gradle.properties - Remove asserts from ItemStackMixin.java - Revert some lines in ItemStackMixin.java --- build.gradle | 206 +++++++++--------- gradle.properties | 1 - .../playerex/mixin/ItemStackMixin.java | 5 +- 3 files changed, 101 insertions(+), 111 deletions(-) diff --git a/build.gradle b/build.gradle index e8e9efc5..57cf8252 100644 --- a/build.gradle +++ b/build.gradle @@ -1,160 +1,154 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { - id 'fabric-loom' version "1.7-SNAPSHOT" - id 'maven-publish' - id "org.jetbrains.kotlin.jvm" version "2.0.0" - id 'org.jetbrains.kotlin.plugin.serialization' version '2.0.0' - id("com.google.devtools.ksp") version "2.0.0-1.0.21" + id 'fabric-loom' version "1.7-SNAPSHOT" + id 'maven-publish' + id "org.jetbrains.kotlin.jvm" version "2.0.0" + id 'org.jetbrains.kotlin.plugin.serialization' version '2.0.0' + id("com.google.devtools.ksp") version "2.0.0-1.0.21" } version = project.mod_version group = project.maven_group base { - archivesName = project.archives_base_name + archivesName = project.archives_base_name } repositories { - maven { - name = "wispForestReleases" - url = uri("https://maven.wispforest.io/releases") - } - maven { - name = "Ladysnake Mods" - url = 'https://maven.ladysnake.org/releases' - } - maven { - name = "Modrinth" - url = "https://api.modrinth.com/maven" - } - maven { - name = "Nucleoid" - url = "https://maven.nucleoid.xyz/" - } - maven { - url = "https://maven.kosmx.dev/" - } - maven { - name = 'ParchmentMC' - url = 'https://maven.parchmentmc.org' - } - maven { - name = 'Quilt' - url = "https://maven.quiltmc.org/repository/release/" - } - maven { - name = "Terraformers" - url = "https://maven.terraformersmc.com/" - } + maven { + name = "wispForestReleases" + url = uri("https://maven.wispforest.io/releases") + } + maven { + name = "Ladysnake Mods" + url = 'https://maven.ladysnake.org/releases' + } + maven { + name = "Modrinth" + url = "https://api.modrinth.com/maven" + } + maven { + name = "Nucleoid" + url = "https://maven.nucleoid.xyz/" + } + maven { + url = "https://maven.kosmx.dev/" + } + maven { + name = 'ParchmentMC' + url = 'https://maven.parchmentmc.org' + } + maven { + name = 'Quilt' + url = "https://maven.quiltmc.org/repository/release/" + } } loom { splitEnvironmentSourceSets() - mods { - "playerex-directors-cut" { - sourceSet sourceSets.main - sourceSet sourceSets.client - } - } + mods { + "playerex-directors-cut" { + sourceSet sourceSets.main + sourceSet sourceSets.client + } + } } dependencies { - minecraft "com.mojang:minecraft:${project.minecraft_version}" + minecraft "com.mojang:minecraft:${project.minecraft_version}" - mappings loom.layered() { - mappings("org.quiltmc:quilt-mappings:${project.minecraft_version}+build.${project.quilt_mappings_version}:intermediary-v2") - officialMojangMappings() - parchment("org.parchmentmc.data:parchment-${project.parchment_version}@zip") - } + mappings loom.layered() { + mappings("org.quiltmc:quilt-mappings:${project.minecraft_version}+build.${project.quilt_mappings_version}:intermediary-v2") + officialMojangMappings() + parchment("org.parchmentmc.data:parchment-${project.parchment_version}@zip") + } - modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" + modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" - modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" - modImplementation "net.fabricmc:fabric-language-kotlin:${project.fabric_kotlin_version}" + modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" + modImplementation "net.fabricmc:fabric-language-kotlin:${project.fabric_kotlin_version}" - // in-house - modImplementation("maven.modrinth:data-attributes-directors-cut:${project.data_attributes_version}") - modImplementation include("maven.modrinth:opc-directors-cut:${project.opc_version}") + // in-house + modImplementation("maven.modrinth:data-attributes-directors-cut:${project.data_attributes_version}") + modImplementation include("maven.modrinth:opc-directors-cut:${project.opc_version}") - // Cardinal Components - modImplementation include("dev.onyxstudios.cardinal-components-api:cardinal-components-base:${project.cardinal_components_version}") - modImplementation include("dev.onyxstudios.cardinal-components-api:cardinal-components-entity:${project.cardinal_components_version}") - modImplementation include("dev.onyxstudios.cardinal-components-api:cardinal-components-chunk:${project.cardinal_components_version}") - modImplementation include("dev.onyxstudios.cardinal-components-api:cardinal-components-level:${project.cardinal_components_version}") + // Cardinal Components + modImplementation include("dev.onyxstudios.cardinal-components-api:cardinal-components-base:${project.cardinal_components_version}") + modImplementation include("dev.onyxstudios.cardinal-components-api:cardinal-components-entity:${project.cardinal_components_version}") + modImplementation include("dev.onyxstudios.cardinal-components-api:cardinal-components-chunk:${project.cardinal_components_version}") + modImplementation include("dev.onyxstudios.cardinal-components-api:cardinal-components-level:${project.cardinal_components_version}") - modImplementation include("maven.modrinth:AdditionalEntityAttributes:${project.additional_entity_attributes_version}") - modImplementation("maven.modrinth:ranged-weapon-api:${project.ranged_weapon_api_version}") + modImplementation include("maven.modrinth:AdditionalEntityAttributes:${project.additional_entity_attributes_version}") + modImplementation("maven.modrinth:ranged-weapon-api:${project.ranged_weapon_api_version}") - modImplementation include("io.wispforest:endec:${project.endec_version}") - modImplementation include("io.wispforest.endec:gson:${project.endec_gson_version}") - modImplementation include("io.wispforest.endec:netty:${project.endec_netty_version}") + modImplementation include("io.wispforest:endec:${project.endec_version}") + modImplementation include("io.wispforest.endec:gson:${project.endec_gson_version}") + modImplementation include("io.wispforest.endec:netty:${project.endec_netty_version}") - // owo - annotationProcessor modImplementation("io.wispforest:owo-lib:${project.owo_version}") - include "io.wispforest:owo-sentinel:${project.owo_version}" + // owo + annotationProcessor modImplementation("io.wispforest:owo-lib:${project.owo_version}") + include "io.wispforest:owo-sentinel:${project.owo_version}" - implementation("com.google.devtools.ksp:symbol-processing-api:${project.ksp_version}") - implementation("com.squareup:kotlinpoet-ksp:${project.kotlinpoet_version}") - ksp("dev.kosmx.kowoconfig:ksp-owo-config:${project.ksp_owo_config_version}") + implementation("com.google.devtools.ksp:symbol-processing-api:${project.ksp_version}") + implementation("com.squareup:kotlinpoet-ksp:${project.kotlinpoet_version}") + ksp("dev.kosmx.kowoconfig:ksp-owo-config:${project.ksp_owo_config_version}") - modImplementation include("eu.pb4:placeholder-api:${project.placeholder_api_version}") + modImplementation include("eu.pb4:placeholder-api:${project.placeholder_api_version}") - implementation include("net.objecthunter:exp4j:${project.exp4j_version}") + implementation include("net.objecthunter:exp4j:${project.exp4j_version}") - modRuntimeOnly "com.terraformersmc:modmenu:${project.modmenu_version}" - - include(implementation(annotationProcessor("io.github.llamalad7:mixinextras-fabric:${project.mixinextras_version}"))) + include(implementation(annotationProcessor("io.github.llamalad7:mixinextras-fabric:${project.mixinextras_version}"))) } processResources { - inputs.property "version", project.version + inputs.property "version", project.version - filesMatching("fabric.mod.json") { - expand "version": project.version - } + filesMatching("fabric.mod.json") { + expand "version": project.version + } } tasks.withType(JavaCompile).configureEach { - it.options.release = 17 + it.options.release = 17 } tasks.withType(KotlinCompile).configureEach { - kotlinOptions { - jvmTarget = 17 - } + kotlinOptions { + jvmTarget = 17 + } } java { - // Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task - // if it is present. - // If you remove this line, sources will not be generated. - withSourcesJar() + // Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task + // if it is present. + // If you remove this line, sources will not be generated. + withSourcesJar() - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 } jar { - from("LICENSE") { - rename { "${it}_${project.base.archivesName.get()}" } - } + from("LICENSE") { + rename { "${it}_${project.base.archivesName.get()}"} + } } // configure the maven publication publishing { - publications { - mavenJava(MavenPublication) { - from components.java - } - } - - // See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing. - repositories { - // Add repositories to publish to here. - // Notice: This block does NOT have the same function as the block in the top level. - // The repositories here will be used for publishing your artifact, not for - // retrieving dependencies. - } + publications { + mavenJava(MavenPublication) { + from components.java + } + } + + // See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing. + repositories { + // Add repositories to publish to here. + // Notice: This block does NOT have the same function as the block in the top level. + // The repositories here will be used for publishing your artifact, not for + // retrieving dependencies. + } } \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index ad802984..bc08cfa9 100644 --- a/gradle.properties +++ b/gradle.properties @@ -42,6 +42,5 @@ endec_gson_version=0.1.4 endec_netty_version=0.1.3 exp4j_version=0.4.8 -modmenu_version=7.2.2 mixinextras_version=0.4.0 diff --git a/src/main/java/com/bibireden/playerex/mixin/ItemStackMixin.java b/src/main/java/com/bibireden/playerex/mixin/ItemStackMixin.java index 26b3a178..0de14a53 100644 --- a/src/main/java/com/bibireden/playerex/mixin/ItemStackMixin.java +++ b/src/main/java/com/bibireden/playerex/mixin/ItemStackMixin.java @@ -100,7 +100,6 @@ public void preventBreak(int amount, T entity, Consumer if (stack.getItemHolder().is(PlayerEXTags.UNBREAKABLE_ITEMS)) { if (!PlayerEXUtil.isBroken(stack)) { CompoundTag tag = stack.getTag(); - assert tag != null; tag.putBoolean("broken", true); stack.setTag(tag); } @@ -115,7 +114,6 @@ public void removeBrokenOnRepair(int damage, CallbackInfo ci) { ItemStack stack = (ItemStack) (Object) this; if (PlayerEXUtil.isBroken(stack) && damage < stack.getDamageValue()) { CompoundTag tag = stack.getTag(); - assert tag != null; tag.putBoolean("broken", false); stack.setTag(tag); } @@ -156,8 +154,7 @@ public void preventArmour(EquipmentSlot slot, CallbackInfoReturnable entry, AttributeModifier modifier) { - if (modifier.getOperation() != AttributeModifier.Operation.ADDITION) - return ItemStack.ATTRIBUTE_MODIFIER_FORMAT.format(e); + if (modifier.getOperation() != AttributeModifier.Operation.ADDITION) return ItemStack.ATTRIBUTE_MODIFIER_FORMAT.format(e); return ItemStack.ATTRIBUTE_MODIFIER_FORMAT.format(e); } From 8c7d9dc6a132af5479f892c9d0548eb41cf62e96 Mon Sep 17 00:00:00 2001 From: naomi Date: Mon, 16 Sep 2024 19:37:16 +0100 Subject: [PATCH 03/11] [feat] XP increases on kill - Weapon XP increases by a value specified in the config when a mob is killed - Moved XP from an attribute to NBT --- .../playerex/mixin/ItemStackMixin.java | 51 +------------------ .../kotlin/com/bibireden/playerex/PlayerEX.kt | 3 ++ .../api/attribute/PlayerEXAttributes.kt | 3 -- .../playerex/api/items/ItemWithAttributes.kt | 8 --- .../playerex/api/items/WeaponItem.kt | 25 --------- .../playerex/config/PlayerEXConfigModel.kt | 15 ++++++ .../playerex/factory/EventFactory.kt | 34 +++++++++++++ .../bibireden/playerex/util/PlayerEXUtil.kt | 6 +++ 8 files changed, 59 insertions(+), 86 deletions(-) delete mode 100644 src/main/kotlin/com/bibireden/playerex/api/items/ItemWithAttributes.kt delete mode 100644 src/main/kotlin/com/bibireden/playerex/api/items/WeaponItem.kt diff --git a/src/main/java/com/bibireden/playerex/mixin/ItemStackMixin.java b/src/main/java/com/bibireden/playerex/mixin/ItemStackMixin.java index 0de14a53..28541244 100644 --- a/src/main/java/com/bibireden/playerex/mixin/ItemStackMixin.java +++ b/src/main/java/com/bibireden/playerex/mixin/ItemStackMixin.java @@ -1,18 +1,13 @@ package com.bibireden.playerex.mixin; import com.bibireden.data_attributes.api.item.ItemFields; -import com.bibireden.data_attributes.endec.nbt.NbtDeserializer; -import com.bibireden.data_attributes.endec.nbt.NbtSerializer; import com.bibireden.playerex.PlayerEX; import com.bibireden.playerex.api.PlayerEXTags; -import com.bibireden.playerex.api.items.ItemWithAttributes; -import com.bibireden.playerex.api.items.WeaponItem; import com.bibireden.playerex.config.PlayerEXConfigModel; import com.bibireden.playerex.util.PlayerEXUtil; import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; import com.llamalad7.mixinextras.sugar.Local; -import io.wispforest.endec.Endec; import net.minecraft.ChatFormatting; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; @@ -30,7 +25,6 @@ import net.minecraft.world.item.TooltipFlag; import net.minecraft.world.item.context.UseOnContext; import net.minecraft.world.level.Level; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -46,16 +40,7 @@ import java.util.function.Consumer; @Mixin(ItemStack.class) -abstract class ItemStackMixin implements WeaponItem, ItemWithAttributes { - @Unique - private static final Endec> ATTRIBUTES_CODEC = Endec.DOUBLE.mapOf().xmap(HashMap::new, Map::copyOf); - - @Unique - private static final String ATTRIBUTES_KEY = "playerex$attributes"; - - @Unique - private HashMap playerex$attributes; - +abstract class ItemStackMixin { @Shadow public abstract boolean hurt(int amount, RandomSource random, @Nullable ServerPlayer serverPlayer); @@ -252,38 +237,4 @@ public void preventArmour(EquipmentSlot slot, CallbackInfoReturnable cir) { - compoundTag.put(ATTRIBUTES_KEY, ATTRIBUTES_CODEC.encodeFully(NbtSerializer::of, playerex$attributes)); - } - - @SuppressWarnings("AddedMixinMembersNamePattern") - @Override - public double getAttributeValue(@NotNull RangedAttribute attr) { - if (playerex$attributes == null) { - CompoundTag tag = getOrCreateTag(); - playerex$attributes = tag.contains(ATTRIBUTES_KEY) ? ATTRIBUTES_CODEC.decodeFully(NbtDeserializer::of, tag.get(ATTRIBUTES_KEY)) : new HashMap<>(); - } - - return playerex$attributes.computeIfAbsent(attr.getDescriptionId(), s -> attr.getDefaultValue()); - } - - @SuppressWarnings("AddedMixinMembersNamePattern") - @Override - public void setAttributeValue(@NotNull RangedAttribute attr, double value) { - if (playerex$attributes == null) { - CompoundTag tag = getOrCreateTag(); - playerex$attributes = tag.contains(ATTRIBUTES_KEY) ? ATTRIBUTES_CODEC.decodeFully(NbtDeserializer::of, tag.get(ATTRIBUTES_KEY)) : new HashMap<>(); - } - - playerex$attributes.put(attr.getDescriptionId(), value); - } } diff --git a/src/main/kotlin/com/bibireden/playerex/PlayerEX.kt b/src/main/kotlin/com/bibireden/playerex/PlayerEX.kt index 0ded06c7..5d7b5301 100644 --- a/src/main/kotlin/com/bibireden/playerex/PlayerEX.kt +++ b/src/main/kotlin/com/bibireden/playerex/PlayerEX.kt @@ -22,6 +22,7 @@ import de.dafuqs.additionalentityattributes.AdditionalEntityAttributes import eu.pb4.placeholders.api.Placeholders import net.fabricmc.api.ModInitializer import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback +import net.fabricmc.fabric.api.entity.event.v1.ServerEntityCombatEvents import net.fabricmc.fabric.api.entity.event.v1.ServerPlayerEvents import net.fabricmc.fabric.api.networking.v1.ServerLoginConnectionEvents import net.minecraft.core.Registry @@ -79,6 +80,8 @@ object PlayerEX : ModInitializer { DamageFactory.forEach(PlayerEXAPI::registerDamageModification) RefundFactory.forEach(PlayerEXAPI::registerRefundCondition) + ServerEntityCombatEvents.AFTER_KILLED_OTHER_ENTITY.register(EventFactory::entityWasKilled) + PlaceholderFactory.STORE.forEach(Placeholders::register) Registry.register(BuiltInRegistries.SOUND_EVENT, PlayerEXSoundEvents.LEVEL_UP_SOUND.location, PlayerEXSoundEvents.LEVEL_UP_SOUND) diff --git a/src/main/kotlin/com/bibireden/playerex/api/attribute/PlayerEXAttributes.kt b/src/main/kotlin/com/bibireden/playerex/api/attribute/PlayerEXAttributes.kt index d8313da8..8c7415d6 100644 --- a/src/main/kotlin/com/bibireden/playerex/api/attribute/PlayerEXAttributes.kt +++ b/src/main/kotlin/com/bibireden/playerex/api/attribute/PlayerEXAttributes.kt @@ -75,9 +75,6 @@ object PlayerEXAttributes { @JvmField val RANGED_CRITICAL_DAMAGE = register("ranged_crit_damage", 0.0, 0.0, 1_000_000.0) - @JvmField - val EXPERIENCE = register("experience", 0.0, 0.0, 1_000_000_000_000.0) - @ApiStatus.Internal fun register(path: String, base: Double, min: Double, max: Double): RangedAttribute { val attribute = RangedAttribute("attribute.name.${PlayerEX.MOD_ID}.$path", base, min, max) diff --git a/src/main/kotlin/com/bibireden/playerex/api/items/ItemWithAttributes.kt b/src/main/kotlin/com/bibireden/playerex/api/items/ItemWithAttributes.kt deleted file mode 100644 index c862dee2..00000000 --- a/src/main/kotlin/com/bibireden/playerex/api/items/ItemWithAttributes.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.bibireden.playerex.api.items - -import net.minecraft.world.entity.ai.attributes.RangedAttribute - -interface ItemWithAttributes { - fun getAttributeValue(attr: RangedAttribute): Double - fun setAttributeValue(attr: RangedAttribute, value: Double) -} diff --git a/src/main/kotlin/com/bibireden/playerex/api/items/WeaponItem.kt b/src/main/kotlin/com/bibireden/playerex/api/items/WeaponItem.kt deleted file mode 100644 index 4106fd5a..00000000 --- a/src/main/kotlin/com/bibireden/playerex/api/items/WeaponItem.kt +++ /dev/null @@ -1,25 +0,0 @@ -package com.bibireden.playerex.api.items - -import com.bibireden.playerex.api.attribute.PlayerEXAttributes.EXPERIENCE - -interface WeaponItem { - fun isWeapon(): Boolean - - var xp: Double - get() { - val self = this as ItemWithAttributes - - return self.getAttributeValue(EXPERIENCE) - } - set(value) { - val self = this as ItemWithAttributes - - self.setAttributeValue(EXPERIENCE, value) - } - - companion object { - fun getExpReq(level: Int): Double { - return (1.0 / 100.0) * (level * level) + 50.0 - } - } -} diff --git a/src/main/kotlin/com/bibireden/playerex/config/PlayerEXConfigModel.kt b/src/main/kotlin/com/bibireden/playerex/config/PlayerEXConfigModel.kt index fff5993b..dc0d3788 100644 --- a/src/main/kotlin/com/bibireden/playerex/config/PlayerEXConfigModel.kt +++ b/src/main/kotlin/com/bibireden/playerex/config/PlayerEXConfigModel.kt @@ -85,11 +85,26 @@ class PlayerEXConfigModel { var expNegationFactor: Int = 95 data class WeaponLevelingSettings( + @JvmField + var enabled: Boolean = true, + @JvmField var maxLevel: Int = 500, @JvmField var damagePerLevel: Double = 0.1, + + @JvmField + var xpFromPassive: Int = 10, + + @JvmField + var xpFromHostile: Int = 20, + + @JvmField + var xpFromMiniboss: Int = 50, + + @JvmField + var xpFromBoss: Int = 100, ) @JvmField @Nest var weaponLevelingSettings = WeaponLevelingSettings() diff --git a/src/main/kotlin/com/bibireden/playerex/factory/EventFactory.kt b/src/main/kotlin/com/bibireden/playerex/factory/EventFactory.kt index 66efceb3..71681c7d 100644 --- a/src/main/kotlin/com/bibireden/playerex/factory/EventFactory.kt +++ b/src/main/kotlin/com/bibireden/playerex/factory/EventFactory.kt @@ -6,14 +6,20 @@ import com.bibireden.playerex.api.attribute.PlayerEXAttributes import com.bibireden.playerex.components.player.PlayerDataComponent import com.bibireden.playerex.ext.component import com.bibireden.playerex.registry.DamageModificationRegistry +import com.bibireden.playerex.util.PlayerEXUtil +import net.fabricmc.fabric.api.tag.convention.v1.ConventionalEntityTypeTags import net.minecraft.core.registries.BuiltInRegistries +import net.minecraft.nbt.CompoundTag import net.minecraft.server.level.ServerPlayer import net.minecraft.world.damagesource.DamageSource import net.minecraft.world.effect.MobEffects import net.minecraft.world.entity.Entity import net.minecraft.world.entity.LivingEntity +import net.minecraft.world.entity.MobCategory import net.minecraft.world.entity.player.Player import net.minecraft.world.entity.projectile.AbstractArrow +import net.minecraft.world.item.ItemStack +import net.minecraft.world.level.Level object EventFactory { fun reset(oldPlayer: ServerPlayer, newPlayer: ServerPlayer, isAlive: Boolean) @@ -110,4 +116,32 @@ object EventFactory { return original } + fun entityWasKilled(level: Level, entity: Entity, killedEntity: Entity) { + if (PlayerEX.CONFIG.weaponLevelingSettings.enabled) { + when (entity) { + is Player -> { + val item: ItemStack = entity.mainHandItem + val tag: CompoundTag = item.orCreateTag + val currentXp = tag.getInt("Experience") + val xpToAdd = if (killedEntity.type.category.isFriendly) { + PlayerEX.CONFIG.weaponLevelingSettings.xpFromPassive + } else if (killedEntity.type.category == MobCategory.MONSTER) { + if (killedEntity.type.`is`(ConventionalEntityTypeTags.BOSSES)) { + PlayerEX.CONFIG.weaponLevelingSettings.xpFromBoss + } else { + PlayerEX.CONFIG.weaponLevelingSettings.xpFromHostile + } + } else { + 0 + } + + if (PlayerEXUtil.isWeapon(item)) { + PlayerEX.LOGGER.info("Adding ${xpToAdd}xp to ${item.displayName.string}, totalling ${currentXp + xpToAdd}") + tag.putInt("Experience", currentXp + xpToAdd) + } + } + } + } + } + } \ No newline at end of file diff --git a/src/main/kotlin/com/bibireden/playerex/util/PlayerEXUtil.kt b/src/main/kotlin/com/bibireden/playerex/util/PlayerEXUtil.kt index 751ecf53..1d99a76d 100644 --- a/src/main/kotlin/com/bibireden/playerex/util/PlayerEXUtil.kt +++ b/src/main/kotlin/com/bibireden/playerex/util/PlayerEXUtil.kt @@ -2,6 +2,7 @@ package com.bibireden.playerex.util import com.bibireden.data_attributes.api.util.Maths import com.bibireden.playerex.PlayerEX +import com.bibireden.playerex.api.PlayerEXTags import com.bibireden.playerex.ext.level import com.google.common.collect.Multimap import net.minecraft.world.entity.ai.attributes.Attribute @@ -60,6 +61,11 @@ object PlayerEXUtil { return false } + @JvmStatic + fun isWeapon(stack: ItemStack): Boolean { + return stack.`is`(PlayerEXTags.WEAPONS) + } + @JvmStatic /** Removes an [Attribute], [AttributeModifier] pair from the provided [Multimap] **/ fun removeModifier(multimap: Multimap, attribute: Attribute) { From 4e99186a7399ee5e1f8440175216bbdcf194bac9 Mon Sep 17 00:00:00 2001 From: naomi Date: Fri, 20 Sep 2024 14:56:20 +0100 Subject: [PATCH 04/11] [feat] Rudimentary item levelling --- .../playerex/mixin/ItemStackMixin.java | 30 +++++++++++++++- .../playerex/config/PlayerEXConfigModel.kt | 11 ++++++ .../com/bibireden/playerex/ext/ItemStack.kt | 11 ++++++ .../playerex/factory/EventFactory.kt | 16 +++++---- .../bibireden/playerex/util/PlayerEXUtil.kt | 34 +++++++++++++++++++ .../resources/assets/playerex/lang/en_us.json | 14 ++++++++ 6 files changed, 109 insertions(+), 7 deletions(-) create mode 100644 src/main/kotlin/com/bibireden/playerex/ext/ItemStack.kt diff --git a/src/main/java/com/bibireden/playerex/mixin/ItemStackMixin.java b/src/main/java/com/bibireden/playerex/mixin/ItemStackMixin.java index 28541244..d3107af2 100644 --- a/src/main/java/com/bibireden/playerex/mixin/ItemStackMixin.java +++ b/src/main/java/com/bibireden/playerex/mixin/ItemStackMixin.java @@ -105,11 +105,14 @@ public void removeBrokenOnRepair(int damage, CallbackInfo ci) { } @Inject(method = "getAttributeModifiers(Lnet/minecraft/world/entity/EquipmentSlot;)Lcom/google/common/collect/Multimap;", at = @At(value = "RETURN"), cancellable = true) - public void preventArmour(EquipmentSlot slot, CallbackInfoReturnable> cir) { + public void modifyAttributeModifiers(EquipmentSlot slot, CallbackInfoReturnable> cir) { if (!PlayerEX.CONFIG.getItemBreakingEnabled()) return; ItemStack stack = (ItemStack) (Object) this; HashMultimap hashmap = HashMultimap.create(cir.getReturnValue()); + if (PlayerEX.CONFIG.getWeaponLevelingSettings().getEnabled() && PlayerEXUtil.isWeapon(stack)) { + PlayerEXUtil.addToModifier(hashmap, Attributes.ATTACK_DAMAGE, getLevel() * PlayerEX.CONFIG.getWeaponLevelingSettings().getDamagePerLevel()); + } if (PlayerEXUtil.isBroken(stack)) { PlayerEXUtil.removeModifier(hashmap, Attributes.ARMOR); PlayerEXUtil.removeModifier(hashmap, Attributes.ARMOR_TOUGHNESS); @@ -237,4 +240,29 @@ public void preventArmour(EquipmentSlot slot, CallbackInfoReturnable> info, + @Local List list + ) { + ItemStack itemStack = (ItemStack) (Object) this; + if (PlayerEXUtil.isWeapon(itemStack)) { + list.add(Component.translatable("playerex.item.level", getLevel(), PlayerEX.CONFIG.getWeaponLevelingSettings().getMaxLevel())); + list.add(Component.translatable("playerex.item.experience", getXp(), PlayerEXUtil.getRequiredXpForNextLevel(itemStack))); + } + } } diff --git a/src/main/kotlin/com/bibireden/playerex/config/PlayerEXConfigModel.kt b/src/main/kotlin/com/bibireden/playerex/config/PlayerEXConfigModel.kt index dc0d3788..1fed4919 100644 --- a/src/main/kotlin/com/bibireden/playerex/config/PlayerEXConfigModel.kt +++ b/src/main/kotlin/com/bibireden/playerex/config/PlayerEXConfigModel.kt @@ -85,26 +85,37 @@ class PlayerEXConfigModel { var expNegationFactor: Int = 95 data class WeaponLevelingSettings( + @Sync(SyncMode.OVERRIDE_CLIENT) @JvmField var enabled: Boolean = true, + @Sync(SyncMode.OVERRIDE_CLIENT) @JvmField var maxLevel: Int = 500, + @Sync(SyncMode.OVERRIDE_CLIENT) @JvmField var damagePerLevel: Double = 0.1, + @Sync(SyncMode.OVERRIDE_CLIENT) @JvmField var xpFromPassive: Int = 10, + @Sync(SyncMode.OVERRIDE_CLIENT) @JvmField var xpFromHostile: Int = 20, + @Sync(SyncMode.OVERRIDE_CLIENT) @JvmField var xpFromMiniboss: Int = 50, + @Sync(SyncMode.OVERRIDE_CLIENT) @JvmField var xpFromBoss: Int = 100, + + @Sync(SyncMode.OVERRIDE_CLIENT) + @JvmField + var formula: String = "5x^(1.1)" ) @JvmField @Nest var weaponLevelingSettings = WeaponLevelingSettings() diff --git a/src/main/kotlin/com/bibireden/playerex/ext/ItemStack.kt b/src/main/kotlin/com/bibireden/playerex/ext/ItemStack.kt new file mode 100644 index 00000000..d6ca1c96 --- /dev/null +++ b/src/main/kotlin/com/bibireden/playerex/ext/ItemStack.kt @@ -0,0 +1,11 @@ +package com.bibireden.playerex.ext + +import net.minecraft.world.item.ItemStack + +var ItemStack.level: Int + get() = this.orCreateTag.getInt("Level") + set(value) = this.orCreateTag.putInt("Level", value) + +var ItemStack.xp: Int + get() = this.orCreateTag.getInt("Experience") + set(value) = this.orCreateTag.putInt("Experience", value) \ No newline at end of file diff --git a/src/main/kotlin/com/bibireden/playerex/factory/EventFactory.kt b/src/main/kotlin/com/bibireden/playerex/factory/EventFactory.kt index 71681c7d..f66ba6e3 100644 --- a/src/main/kotlin/com/bibireden/playerex/factory/EventFactory.kt +++ b/src/main/kotlin/com/bibireden/playerex/factory/EventFactory.kt @@ -5,11 +5,12 @@ import com.bibireden.playerex.PlayerEX import com.bibireden.playerex.api.attribute.PlayerEXAttributes import com.bibireden.playerex.components.player.PlayerDataComponent import com.bibireden.playerex.ext.component +import com.bibireden.playerex.ext.level +import com.bibireden.playerex.ext.xp import com.bibireden.playerex.registry.DamageModificationRegistry import com.bibireden.playerex.util.PlayerEXUtil import net.fabricmc.fabric.api.tag.convention.v1.ConventionalEntityTypeTags import net.minecraft.core.registries.BuiltInRegistries -import net.minecraft.nbt.CompoundTag import net.minecraft.server.level.ServerPlayer import net.minecraft.world.damagesource.DamageSource import net.minecraft.world.effect.MobEffects @@ -121,9 +122,7 @@ object EventFactory { when (entity) { is Player -> { val item: ItemStack = entity.mainHandItem - val tag: CompoundTag = item.orCreateTag - val currentXp = tag.getInt("Experience") - val xpToAdd = if (killedEntity.type.category.isFriendly) { + var xpToAdd = if (killedEntity.type.category.isFriendly) { PlayerEX.CONFIG.weaponLevelingSettings.xpFromPassive } else if (killedEntity.type.category == MobCategory.MONSTER) { if (killedEntity.type.`is`(ConventionalEntityTypeTags.BOSSES)) { @@ -136,8 +135,13 @@ object EventFactory { } if (PlayerEXUtil.isWeapon(item)) { - PlayerEX.LOGGER.info("Adding ${xpToAdd}xp to ${item.displayName.string}, totalling ${currentXp + xpToAdd}") - tag.putInt("Experience", currentXp + xpToAdd) + var nextLevel = PlayerEXUtil.getRequiredXpForNextLevel(item) + item.xp += xpToAdd + while (item.xp >= nextLevel && item.level < PlayerEX.CONFIG.weaponLevelingSettings.maxLevel) { + item.xp -= nextLevel + item.level += 1 + nextLevel = PlayerEXUtil.getRequiredXpForNextLevel(item) + } } } } diff --git a/src/main/kotlin/com/bibireden/playerex/util/PlayerEXUtil.kt b/src/main/kotlin/com/bibireden/playerex/util/PlayerEXUtil.kt index 1d99a76d..66fb51aa 100644 --- a/src/main/kotlin/com/bibireden/playerex/util/PlayerEXUtil.kt +++ b/src/main/kotlin/com/bibireden/playerex/util/PlayerEXUtil.kt @@ -4,6 +4,7 @@ import com.bibireden.data_attributes.api.util.Maths import com.bibireden.playerex.PlayerEX import com.bibireden.playerex.api.PlayerEXTags import com.bibireden.playerex.ext.level +import com.bibireden.playerex.ext.xp import com.google.common.collect.Multimap import net.minecraft.world.entity.ai.attributes.Attribute import net.minecraft.world.entity.ai.attributes.AttributeModifier @@ -34,6 +35,14 @@ object PlayerEXUtil { return ExpressionBuilder(PlayerEX.CONFIG.levelFormula).variable(VARIABLE).function(STAIRCASE_FUNCTION).build() } + private val itemExpression: Expression + get() = createItemExpression() + + @JvmStatic + private fun createItemExpression(): Expression { + return ExpressionBuilder(PlayerEX.CONFIG.weaponLevelingSettings.formula).variable(VARIABLE).build() + } + @JvmStatic /** Computes the experience cost of the provided level. */ fun getRequiredXpForLevel(player: Player, target: Double): Int { @@ -53,6 +62,19 @@ object PlayerEXUtil { @JvmStatic fun getRequiredXpForNextLevel(player: Player): Int = getRequiredXpForLevel(player, player.level + 1) + @JvmStatic + fun getRequiredXpForLevel(item: ItemStack, target: Int): Int { + if (target <= item.level) return 0 + var acc = 0 + for (x in item.level+1..target) { + acc += abs(round(itemExpression.setVariable(VARIABLE, (x).toDouble()).evaluate())).toInt() + } + return acc + } + + @JvmStatic + fun getRequiredXpForNextLevel(item: ItemStack): Int = getRequiredXpForLevel(item, item.level + 1) + @JvmStatic fun isBroken(stack: ItemStack): Boolean { if (stack.tag != null) { @@ -77,4 +99,16 @@ object PlayerEXUtil { multimap.put(attribute, newModifier) } } + + @JvmStatic + /** Adds a [Double] to the value of an [AttributeModifier] from the provided [Multimap] **/ + fun addToModifier(multimap: Multimap, attribute: Attribute, amount: Double) { + val optional = multimap[attribute].stream().findFirst() + if (optional.isPresent) { + val modifier = optional.get() + val newModifier = AttributeModifier(modifier.id, modifier.name, modifier.amount + amount, modifier.operation) + multimap.remove(attribute, modifier) + multimap.put(attribute, newModifier) + } + } } diff --git a/src/main/resources/assets/playerex/lang/en_us.json b/src/main/resources/assets/playerex/lang/en_us.json index 9b7b484b..547c057e 100644 --- a/src/main/resources/assets/playerex/lang/en_us.json +++ b/src/main/resources/assets/playerex/lang/en_us.json @@ -76,6 +76,20 @@ "playerex.broken": "Broken", + "playerex.item.level": [ + {"text": "Level: "}, + {"index": 0}, + {"text": "/"}, + {"index": 1} + ], + + "playerex.item.experience": [ + {"text": "Exp: "}, + {"index": 0}, + {"text": "/"}, + {"index": 1} + ], + "playerex.command.reset_chunk": "Reset experience negation factor for chunk at %s", "playerex.command.refund": "Refunded %s skill points for player %s", From aef8654ec558a133f59657782ae11638a9004a81 Mon Sep 17 00:00:00 2001 From: naomi Date: Fri, 20 Sep 2024 19:50:11 +0100 Subject: [PATCH 05/11] [feat] Rudimentary armour levelling --- .../playerex/mixin/ItemStackMixin.java | 7 ++- .../bibireden/playerex/api/PlayerEXTags.kt | 3 ++ .../playerex/config/PlayerEXConfigModel.kt | 36 +++++++++++++ .../playerex/factory/EventFactory.kt | 44 +++++++++------- .../bibireden/playerex/util/PlayerEXUtil.kt | 51 +++++++++++++++++-- .../data/playerex/tags/items/armor.json | 30 +++++++++++ .../data/playerex/tags/items/weapons.json | 21 ++++++++ 7 files changed, 168 insertions(+), 24 deletions(-) create mode 100644 src/main/resources/data/playerex/tags/items/armor.json diff --git a/src/main/java/com/bibireden/playerex/mixin/ItemStackMixin.java b/src/main/java/com/bibireden/playerex/mixin/ItemStackMixin.java index d3107af2..59777027 100644 --- a/src/main/java/com/bibireden/playerex/mixin/ItemStackMixin.java +++ b/src/main/java/com/bibireden/playerex/mixin/ItemStackMixin.java @@ -113,6 +113,9 @@ public void modifyAttributeModifiers(EquipmentSlot slot, CallbackInfoReturnable< if (PlayerEX.CONFIG.getWeaponLevelingSettings().getEnabled() && PlayerEXUtil.isWeapon(stack)) { PlayerEXUtil.addToModifier(hashmap, Attributes.ATTACK_DAMAGE, getLevel() * PlayerEX.CONFIG.getWeaponLevelingSettings().getDamagePerLevel()); } + if (PlayerEX.CONFIG.getArmorLevelingSettings().getEnabled() && PlayerEXUtil.isArmor(stack)) { + PlayerEXUtil.addToModifier(hashmap, Attributes.ARMOR, getLevel() * PlayerEX.CONFIG.getArmorLevelingSettings().getArmorPerLevel()); + } if (PlayerEXUtil.isBroken(stack)) { PlayerEXUtil.removeModifier(hashmap, Attributes.ARMOR); PlayerEXUtil.removeModifier(hashmap, Attributes.ARMOR_TOUGHNESS); @@ -260,8 +263,8 @@ private int getXp() { @Local List list ) { ItemStack itemStack = (ItemStack) (Object) this; - if (PlayerEXUtil.isWeapon(itemStack)) { - list.add(Component.translatable("playerex.item.level", getLevel(), PlayerEX.CONFIG.getWeaponLevelingSettings().getMaxLevel())); + if (PlayerEXUtil.isLevelable(itemStack)) { + list.add(Component.translatable("playerex.item.level", getLevel(), PlayerEXUtil.getMaxLevel(itemStack))); list.add(Component.translatable("playerex.item.experience", getXp(), PlayerEXUtil.getRequiredXpForNextLevel(itemStack))); } } diff --git a/src/main/kotlin/com/bibireden/playerex/api/PlayerEXTags.kt b/src/main/kotlin/com/bibireden/playerex/api/PlayerEXTags.kt index 0ec11b76..7e109687 100644 --- a/src/main/kotlin/com/bibireden/playerex/api/PlayerEXTags.kt +++ b/src/main/kotlin/com/bibireden/playerex/api/PlayerEXTags.kt @@ -11,4 +11,7 @@ object PlayerEXTags { @JvmField val WEAPONS: TagKey = TagKey.create(Registries.ITEM, PlayerEX.id("weapons")) + + @JvmField + val ARMOR: TagKey = TagKey.create(Registries.ITEM, PlayerEX.id("armor")) } diff --git a/src/main/kotlin/com/bibireden/playerex/config/PlayerEXConfigModel.kt b/src/main/kotlin/com/bibireden/playerex/config/PlayerEXConfigModel.kt index 1fed4919..31207c43 100644 --- a/src/main/kotlin/com/bibireden/playerex/config/PlayerEXConfigModel.kt +++ b/src/main/kotlin/com/bibireden/playerex/config/PlayerEXConfigModel.kt @@ -120,5 +120,41 @@ class PlayerEXConfigModel { @JvmField @Nest var weaponLevelingSettings = WeaponLevelingSettings() + data class ArmorLevelingSettings( + @Sync(SyncMode.OVERRIDE_CLIENT) + @JvmField + var enabled: Boolean = true, + + @Sync(SyncMode.OVERRIDE_CLIENT) + @JvmField + var maxLevel: Int = 500, + + @Sync(SyncMode.OVERRIDE_CLIENT) + @JvmField + var armorPerLevel: Double = 0.1, + + @Sync(SyncMode.OVERRIDE_CLIENT) + @JvmField + var xpFromPassive: Int = 10, + + @Sync(SyncMode.OVERRIDE_CLIENT) + @JvmField + var xpFromHostile: Int = 20, + + @Sync(SyncMode.OVERRIDE_CLIENT) + @JvmField + var xpFromMiniboss: Int = 50, + + @Sync(SyncMode.OVERRIDE_CLIENT) + @JvmField + var xpFromBoss: Int = 100, + + @Sync(SyncMode.OVERRIDE_CLIENT) + @JvmField + var formula: String = "5x^(1.2)" + ) + + @JvmField @Nest var armorLevelingSettings = ArmorLevelingSettings() + enum class Tooltip { Default, Vanilla, PlayerEX } } \ No newline at end of file diff --git a/src/main/kotlin/com/bibireden/playerex/factory/EventFactory.kt b/src/main/kotlin/com/bibireden/playerex/factory/EventFactory.kt index f66ba6e3..889bb90c 100644 --- a/src/main/kotlin/com/bibireden/playerex/factory/EventFactory.kt +++ b/src/main/kotlin/com/bibireden/playerex/factory/EventFactory.kt @@ -121,31 +121,39 @@ object EventFactory { if (PlayerEX.CONFIG.weaponLevelingSettings.enabled) { when (entity) { is Player -> { - val item: ItemStack = entity.mainHandItem - var xpToAdd = if (killedEntity.type.category.isFriendly) { - PlayerEX.CONFIG.weaponLevelingSettings.xpFromPassive - } else if (killedEntity.type.category == MobCategory.MONSTER) { - if (killedEntity.type.`is`(ConventionalEntityTypeTags.BOSSES)) { - PlayerEX.CONFIG.weaponLevelingSettings.xpFromBoss + val mainHandItem: ItemStack = entity.mainHandItem + + if (PlayerEXUtil.isLevelable(mainHandItem)) { + PlayerEXUtil.levelItem(mainHandItem, if (killedEntity.type.category.isFriendly) { + PlayerEX.CONFIG.weaponLevelingSettings.xpFromPassive + } else if (killedEntity.type.category == MobCategory.MONSTER) { + if (killedEntity.type.`is`(ConventionalEntityTypeTags.BOSSES)) { + PlayerEX.CONFIG.weaponLevelingSettings.xpFromBoss + } else { + PlayerEX.CONFIG.weaponLevelingSettings.xpFromHostile + } } else { - PlayerEX.CONFIG.weaponLevelingSettings.xpFromHostile - } - } else { - 0 + 0 + }, PlayerEX.CONFIG.weaponLevelingSettings.maxLevel) } - if (PlayerEXUtil.isWeapon(item)) { - var nextLevel = PlayerEXUtil.getRequiredXpForNextLevel(item) - item.xp += xpToAdd - while (item.xp >= nextLevel && item.level < PlayerEX.CONFIG.weaponLevelingSettings.maxLevel) { - item.xp -= nextLevel - item.level += 1 - nextLevel = PlayerEXUtil.getRequiredXpForNextLevel(item) + for (item in entity.armorSlots) { + if (PlayerEXUtil.isLevelable(item)) { + PlayerEXUtil.levelItem(item, if (killedEntity.type.category.isFriendly) { + PlayerEX.CONFIG.armorLevelingSettings.xpFromPassive + } else if (killedEntity.type.category == MobCategory.MONSTER) { + if (killedEntity.type.`is`(ConventionalEntityTypeTags.BOSSES)) { + PlayerEX.CONFIG.armorLevelingSettings.xpFromBoss + } else { + PlayerEX.CONFIG.armorLevelingSettings.xpFromHostile + } + } else { + 0 + }, PlayerEX.CONFIG.armorLevelingSettings.maxLevel) } } } } } } - } \ No newline at end of file diff --git a/src/main/kotlin/com/bibireden/playerex/util/PlayerEXUtil.kt b/src/main/kotlin/com/bibireden/playerex/util/PlayerEXUtil.kt index 66fb51aa..5f474f11 100644 --- a/src/main/kotlin/com/bibireden/playerex/util/PlayerEXUtil.kt +++ b/src/main/kotlin/com/bibireden/playerex/util/PlayerEXUtil.kt @@ -35,13 +35,20 @@ object PlayerEXUtil { return ExpressionBuilder(PlayerEX.CONFIG.levelFormula).variable(VARIABLE).function(STAIRCASE_FUNCTION).build() } - private val itemExpression: Expression - get() = createItemExpression() + private val weaponExpression: Expression + get() = createWeaponExpression() @JvmStatic - private fun createItemExpression(): Expression { + private fun createWeaponExpression(): Expression { return ExpressionBuilder(PlayerEX.CONFIG.weaponLevelingSettings.formula).variable(VARIABLE).build() } + private val armorExpression: Expression + get() = createArmorExpression() + + @JvmStatic + private fun createArmorExpression(): Expression { + return ExpressionBuilder(PlayerEX.CONFIG.armorLevelingSettings.formula).variable(VARIABLE).build() + } @JvmStatic /** Computes the experience cost of the provided level. */ @@ -67,7 +74,10 @@ object PlayerEXUtil { if (target <= item.level) return 0 var acc = 0 for (x in item.level+1..target) { - acc += abs(round(itemExpression.setVariable(VARIABLE, (x).toDouble()).evaluate())).toInt() + when { + isWeapon(item) -> acc += abs(round(weaponExpression.setVariable(VARIABLE, (x).toDouble()).evaluate())).toInt() + isArmor(item) -> acc += abs(round(armorExpression.setVariable(VARIABLE, (x).toDouble()).evaluate())).toInt() + } } return acc } @@ -75,6 +85,15 @@ object PlayerEXUtil { @JvmStatic fun getRequiredXpForNextLevel(item: ItemStack): Int = getRequiredXpForLevel(item, item.level + 1) + @JvmStatic + fun getMaxLevel(item: ItemStack): Int { + return when { + isWeapon(item) -> PlayerEX.CONFIG.weaponLevelingSettings.maxLevel + isArmor(item) -> PlayerEX.CONFIG.armorLevelingSettings.maxLevel + else -> 0 + } + } + @JvmStatic fun isBroken(stack: ItemStack): Boolean { if (stack.tag != null) { @@ -88,6 +107,11 @@ object PlayerEXUtil { return stack.`is`(PlayerEXTags.WEAPONS) } + @JvmStatic + fun isArmor(stack: ItemStack): Boolean { + return stack.`is`(PlayerEXTags.ARMOR) + } + @JvmStatic /** Removes an [Attribute], [AttributeModifier] pair from the provided [Multimap] **/ fun removeModifier(multimap: Multimap, attribute: Attribute) { @@ -111,4 +135,23 @@ object PlayerEXUtil { multimap.put(attribute, newModifier) } } + + @JvmStatic + fun isLevelable(stack: ItemStack): Boolean { + return (isWeapon(stack) && PlayerEX.CONFIG.weaponLevelingSettings.enabled) + || (isArmor(stack) && PlayerEX.CONFIG.armorLevelingSettings.enabled) + } + + @JvmStatic + fun levelItem(itemStack: ItemStack, xpToAdd: Int, maxLevel: Int) { + if (isLevelable(itemStack)) { + var nextLevel = getRequiredXpForNextLevel(itemStack) + itemStack.xp += xpToAdd + while (itemStack.xp >= nextLevel && itemStack.level < maxLevel) { + itemStack.xp -= nextLevel + itemStack.level += 1 + nextLevel = getRequiredXpForNextLevel(itemStack) + } + } + } } diff --git a/src/main/resources/data/playerex/tags/items/armor.json b/src/main/resources/data/playerex/tags/items/armor.json new file mode 100644 index 00000000..da34e96f --- /dev/null +++ b/src/main/resources/data/playerex/tags/items/armor.json @@ -0,0 +1,30 @@ +{ + "replace": false, + "values": [ + "minecraft:leather_helmet", + "minecraft:leather_chestplate", + "minecraft:leather_leggings", + "minecraft:leather_boots", + "minecraft:chainmail_helmet", + "minecraft:chainmail_chestplate", + "minecraft:chainmail_leggings", + "minecraft:chainmail_boots", + "minecraft:iron_helmet", + "minecraft:iron_chestplate", + "minecraft:iron_leggings", + "minecraft:iron_boots", + "minecraft:golden_helmet", + "minecraft:golden_chestplate", + "minecraft:golden_leggings", + "minecraft:golden_boots", + "minecraft:diamond_helmet", + "minecraft:diamond_chestplate", + "minecraft:diamond_leggings", + "minecraft:diamond_boots", + "minecraft:netherite_helmet", + "minecraft:netherite_chestplate", + "minecraft:netherite_leggings", + "minecraft:netherite_boots", + "minecraft:turtle_helmet" + ] +} \ No newline at end of file diff --git a/src/main/resources/data/playerex/tags/items/weapons.json b/src/main/resources/data/playerex/tags/items/weapons.json index cd948b27..587cfc5d 100644 --- a/src/main/resources/data/playerex/tags/items/weapons.json +++ b/src/main/resources/data/playerex/tags/items/weapons.json @@ -1,5 +1,26 @@ { + "replace": false, "values": [ + { + "id": "#c:swords", + "required": false + }, + { + "id": "#c:axes", + "required": false + }, + { + "id": "#c:spears", + "required": false + }, + { + "id": "#c:shields", + "required": false + }, + { + "id": "#c:bows", + "required": false + }, "#minecraft:swords", "#minecraft:axes", "minecraft:bow", From b095dac1927ce356205a175b9c878c03f9965eb0 Mon Sep 17 00:00:00 2001 From: naomi Date: Thu, 24 Oct 2024 23:33:23 +0100 Subject: [PATCH 06/11] Changes to tooltip colouring --- .../resources/assets/playerex/lang/en_us.json | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/main/resources/assets/playerex/lang/en_us.json b/src/main/resources/assets/playerex/lang/en_us.json index 4f072e5a..7a7ee859 100644 --- a/src/main/resources/assets/playerex/lang/en_us.json +++ b/src/main/resources/assets/playerex/lang/en_us.json @@ -77,17 +77,17 @@ "playerex.broken": "Broken", "playerex.item.level": [ - {"text": "Level: "}, - {"index": 0}, - {"text": "/"}, - {"index": 1} + {"text": "Level: ", "color": "#6EBAE5"}, + {"index": 0, "color": "gold"}, + {"text": "/", "color": "gold"}, + {"index": 1, "color": "gold"} ], "playerex.item.experience": [ - {"text": "Exp: "}, - {"index": 0}, - {"text": "/"}, - {"index": 1} + {"text": "Exp: ", "color": "#6EBAE5"}, + {"index": 0, "color": "gold"}, + {"text": "/", "color": "gold"}, + {"index": 1, "color": "gold"} ], "playerex.command.reset_chunk": "Reset experience negation factor for chunk at %s", From 73e6718b412b934d8cbf16f8704009cd7d7fbb61 Mon Sep 17 00:00:00 2001 From: Naomi Roberts Date: Fri, 13 Dec 2024 15:33:16 +0000 Subject: [PATCH 07/11] [feat] Improve levelling config --- .../playerex/mixin/ItemStackMixin.java | 2 + .../playerex/config/PlayerEXConfigModel.kt | 29 +++--- .../playerex/factory/EventFactory.kt | 90 +++++++++++-------- .../resources/assets/playerex/lang/en_us.json | 25 +++++- 4 files changed, 98 insertions(+), 48 deletions(-) diff --git a/src/main/java/com/bibireden/playerex/mixin/ItemStackMixin.java b/src/main/java/com/bibireden/playerex/mixin/ItemStackMixin.java index 59777027..bbb0fb11 100644 --- a/src/main/java/com/bibireden/playerex/mixin/ItemStackMixin.java +++ b/src/main/java/com/bibireden/playerex/mixin/ItemStackMixin.java @@ -115,6 +115,8 @@ public void modifyAttributeModifiers(EquipmentSlot slot, CallbackInfoReturnable< } if (PlayerEX.CONFIG.getArmorLevelingSettings().getEnabled() && PlayerEXUtil.isArmor(stack)) { PlayerEXUtil.addToModifier(hashmap, Attributes.ARMOR, getLevel() * PlayerEX.CONFIG.getArmorLevelingSettings().getArmorPerLevel()); + // TODO: % Damage reduction + // PlayerEXUtil.addToModifier(hashmap, , getLevel() * PlayerEX.CONFIG.getArmorLevelingSettings().getStatPerLevel()); } if (PlayerEXUtil.isBroken(stack)) { PlayerEXUtil.removeModifier(hashmap, Attributes.ARMOR); diff --git a/src/main/kotlin/com/bibireden/playerex/config/PlayerEXConfigModel.kt b/src/main/kotlin/com/bibireden/playerex/config/PlayerEXConfigModel.kt index 31207c43..81f70852 100644 --- a/src/main/kotlin/com/bibireden/playerex/config/PlayerEXConfigModel.kt +++ b/src/main/kotlin/com/bibireden/playerex/config/PlayerEXConfigModel.kt @@ -84,18 +84,26 @@ class PlayerEXConfigModel { @JvmField var expNegationFactor: Int = 95 - data class WeaponLevelingSettings( + data class ArmorXpSettings( @Sync(SyncMode.OVERRIDE_CLIENT) @JvmField var enabled: Boolean = true, @Sync(SyncMode.OVERRIDE_CLIENT) @JvmField - var maxLevel: Int = 500, + var armorPerLevel: Double = 0.1, @Sync(SyncMode.OVERRIDE_CLIENT) @JvmField - var damagePerLevel: Double = 0.1, + var reductionPerLevel: Double = 1.0, + + @Sync(SyncMode.OVERRIDE_CLIENT) + @JvmField + var maxReduction: Double = 1.0, + + @Sync(SyncMode.OVERRIDE_CLIENT) + @JvmField + var formula: String = "5x^(1.1)", @Sync(SyncMode.OVERRIDE_CLIENT) @JvmField @@ -115,23 +123,21 @@ class PlayerEXConfigModel { @Sync(SyncMode.OVERRIDE_CLIENT) @JvmField - var formula: String = "5x^(1.1)" + var maxLevel: Int = 500, ) - @JvmField @Nest var weaponLevelingSettings = WeaponLevelingSettings() - - data class ArmorLevelingSettings( + data class WeaponXpSettings( @Sync(SyncMode.OVERRIDE_CLIENT) @JvmField var enabled: Boolean = true, @Sync(SyncMode.OVERRIDE_CLIENT) @JvmField - var maxLevel: Int = 500, + var damagePerLevel: Double = 0.1, @Sync(SyncMode.OVERRIDE_CLIENT) @JvmField - var armorPerLevel: Double = 0.1, + var formula: String = "5x^(1.1)", @Sync(SyncMode.OVERRIDE_CLIENT) @JvmField @@ -151,10 +157,11 @@ class PlayerEXConfigModel { @Sync(SyncMode.OVERRIDE_CLIENT) @JvmField - var formula: String = "5x^(1.2)" + var maxLevel: Int = 500, ) - @JvmField @Nest var armorLevelingSettings = ArmorLevelingSettings() + @JvmField @Nest var weaponLevelingSettings = WeaponXpSettings() + @JvmField @Nest var armorLevelingSettings = ArmorXpSettings() enum class Tooltip { Default, Vanilla, PlayerEX } } \ No newline at end of file diff --git a/src/main/kotlin/com/bibireden/playerex/factory/EventFactory.kt b/src/main/kotlin/com/bibireden/playerex/factory/EventFactory.kt index bb3227d8..fc3275f8 100644 --- a/src/main/kotlin/com/bibireden/playerex/factory/EventFactory.kt +++ b/src/main/kotlin/com/bibireden/playerex/factory/EventFactory.kt @@ -4,9 +4,8 @@ import com.bibireden.data_attributes.api.DataAttributesAPI import com.bibireden.playerex.PlayerEX import com.bibireden.playerex.api.attribute.PlayerEXAttributes import com.bibireden.playerex.components.player.PlayerDataComponent +import com.bibireden.playerex.config.PlayerEXConfig import com.bibireden.playerex.ext.component -import com.bibireden.playerex.ext.level -import com.bibireden.playerex.ext.xp import com.bibireden.playerex.registry.DamageModificationRegistry import com.bibireden.playerex.util.PlayerEXUtil import net.fabricmc.fabric.api.tag.convention.v1.ConventionalEntityTypeTags @@ -110,42 +109,61 @@ object EventFactory { } fun entityWasKilled(level: Level, entity: Entity, killedEntity: Entity) { - if (PlayerEX.CONFIG.weaponLevelingSettings.enabled) { - when (entity) { - is Player -> { - val mainHandItem: ItemStack = entity.mainHandItem - - if (PlayerEXUtil.isLevelable(mainHandItem)) { - PlayerEXUtil.levelItem(mainHandItem, if (killedEntity.type.category.isFriendly) { - PlayerEX.CONFIG.weaponLevelingSettings.xpFromPassive - } else if (killedEntity.type.category == MobCategory.MONSTER) { - if (killedEntity.type.`is`(ConventionalEntityTypeTags.BOSSES)) { - PlayerEX.CONFIG.weaponLevelingSettings.xpFromBoss - } else { - PlayerEX.CONFIG.weaponLevelingSettings.xpFromHostile - } - } else { - 0 - }, PlayerEX.CONFIG.weaponLevelingSettings.maxLevel) - } - - for (item in entity.armorSlots) { - if (PlayerEXUtil.isLevelable(item)) { - PlayerEXUtil.levelItem(item, if (killedEntity.type.category.isFriendly) { - PlayerEX.CONFIG.armorLevelingSettings.xpFromPassive - } else if (killedEntity.type.category == MobCategory.MONSTER) { - if (killedEntity.type.`is`(ConventionalEntityTypeTags.BOSSES)) { - PlayerEX.CONFIG.armorLevelingSettings.xpFromBoss - } else { - PlayerEX.CONFIG.armorLevelingSettings.xpFromHostile - } - } else { - 0 - }, PlayerEX.CONFIG.armorLevelingSettings.maxLevel) - } - } + when (entity) { + is Player -> { + val mainHandItem: ItemStack = entity.mainHandItem + tryLevelItem(mainHandItem, PlayerEX.CONFIG.weaponLevelingSettings, killedEntity) + + for (item in entity.armorSlots) { + tryLevelItem(item, PlayerEX.CONFIG.armorLevelingSettings, killedEntity) } } } } + + private fun tryLevelItem(item: ItemStack, xpSettings: PlayerEXConfig.ArmorXpSettings, killedEntity: Entity) { + tryLevelItem(item, + xpSettings.enabled, + xpSettings.xpFromPassive, + xpSettings.xpFromBoss, + xpSettings.xpFromHostile, + xpSettings.maxLevel, + killedEntity + ) + } + + private fun tryLevelItem(item: ItemStack, xpSettings: PlayerEXConfig.WeaponXpSettings, killedEntity: Entity) { + tryLevelItem(item, + xpSettings.enabled, + xpSettings.xpFromPassive, + xpSettings.xpFromBoss, + xpSettings.xpFromHostile, + xpSettings.maxLevel, + killedEntity + ) + } + + private fun tryLevelItem( + item: ItemStack, + enabled: Boolean, + xpFromPassive: Int, + xpFromBoss: Int, + xpFromHostile: Int, + maxLevel: Int, + killedEntity: Entity + ) { + if (PlayerEXUtil.isLevelable(item) && enabled) { + PlayerEXUtil.levelItem(item, if (killedEntity.type.category.isFriendly) { + xpFromPassive + } else if (killedEntity.type.category == MobCategory.MONSTER) { + if (killedEntity.type.`is`(ConventionalEntityTypeTags.BOSSES)) { + xpFromBoss + } else { + xpFromHostile + } + } else { + 0 + }, maxLevel) + } + } } \ No newline at end of file diff --git a/src/main/resources/assets/playerex/lang/en_us.json b/src/main/resources/assets/playerex/lang/en_us.json index 7a7ee859..c05c8817 100644 --- a/src/main/resources/assets/playerex/lang/en_us.json +++ b/src/main/resources/assets/playerex/lang/en_us.json @@ -203,5 +203,28 @@ "text.config.playerex-config.option.restorativeForceMultiplier": "Restorative Force Multiplier", "text.config.playerex-config.option.expNegationFactor": "Experience Negation Factor", - "text.config.playerex-config.option.disableUI": "Disable UI" + "text.config.playerex-config.option.disableUI": "Disable UI", + + "text.config.playerex-config.category.weaponLevelingSettings": "Weapon Leveling", + "text.config.playerex-config.option.weaponLevelingSettings.enabled": "Activated", + "text.config.playerex-config.option.weaponLevelingSettings.damagePerLevel": "Attack Damage per Level", + "text.config.playerex-config.option.weaponLevelingSettings.formula": "XP Formula", + "text.config.playerex-config.option.weaponLevelingSettings.xpFromPassive": "XP from Passive Mobs", + "text.config.playerex-config.option.weaponLevelingSettings.xpFromHostile": "XP from Hostile Mobs", + "text.config.playerex-config.option.weaponLevelingSettings.xpFromMiniboss": "XP from Minibosses (unused)", + "text.config.playerex-config.option.weaponLevelingSettings.xpFromBoss": "XP from Bosses", + "text.config.playerex-config.option.weaponLevelingSettings.maxLevel": "Maximum Level", + + "text.config.playerex-config.category.armorLevelingSettings": "Armor Leveling", + "text.config.playerex-config.option.armorLevelingSettings.enabled": "Activated", + "text.config.playerex-config.option.armorLevelingSettings.armorPerLevel": "Armor per Level", + "text.config.playerex-config.option.armorLevelingSettings.reductionPerLevel": "% Damage Reduction per Level", + "text.config.playerex-config.option.armorLevelingSettings.maxReduction": "Maximum % Damage Reduction", + "text.config.playerex-config.option.armorLevelingSettings.formula": "XP Formula", + "text.config.playerex-config.option.armorLevelingSettings.xpFromPassive": "XP from Passive Mobs", + "text.config.playerex-config.option.armorLevelingSettings.xpFromHostile": "XP from Hostile Mobs", + "text.config.playerex-config.option.armorLevelingSettings.xpFromMiniboss": "XP from Minibosses (unused)", + "text.config.playerex-config.option.armorLevelingSettings.xpFromBoss": "XP from Bosses", + "text.config.playerex-config.option.armorLevelingSettings.maxLevel": "Maximum Level", + "text.config.playerex-config.option.armorLevelingSettings.reduction": "Damage Reduction" } \ No newline at end of file From 8a4fae5fd94f58304dc9c95be8ca0e87922d2039 Mon Sep 17 00:00:00 2001 From: Naomi Roberts Date: Fri, 13 Dec 2024 15:59:38 +0000 Subject: [PATCH 08/11] [fix] Add back accidentally removed translation key --- src/main/resources/assets/playerex/lang/en_us.json | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/resources/assets/playerex/lang/en_us.json b/src/main/resources/assets/playerex/lang/en_us.json index 1a42e285..07d794fe 100644 --- a/src/main/resources/assets/playerex/lang/en_us.json +++ b/src/main/resources/assets/playerex/lang/en_us.json @@ -212,6 +212,7 @@ "text.config.playerex-config.category.soundSettings": "Sound Options", "text.config.playerex-config.option.soundSettings.levelUpVolume": "Level Up Volume", "text.config.playerex-config.option.soundSettings.skillUpVolume": "Skill Up Volume", + "text.config.playerex-config.option.soundSettings.refundVolume": "Refund Volume", "text.config.playerex-config.category.weaponLevelingSettings": "Weapon Leveling", "text.config.playerex-config.option.weaponLevelingSettings.enabled": "Activated", From 17f0f1598db27291a68d9f6de862afb37eaf726a Mon Sep 17 00:00:00 2001 From: Naomi Roberts Date: Fri, 13 Dec 2024 18:56:03 +0000 Subject: [PATCH 09/11] [feat] Implement percent damage reduction --- .../playerex/mixin/ItemStackMixin.java | 23 +++++++++++++++---- .../playerex/mixin/LivingEntityMixin.java | 16 +++++++++++++ .../playerex/config/PlayerEXConfigModel.kt | 5 +--- .../resources/assets/playerex/lang/en_us.json | 10 +++++--- src/main/resources/playerex.mixins.json | 4 ++-- 5 files changed, 45 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/bibireden/playerex/mixin/ItemStackMixin.java b/src/main/java/com/bibireden/playerex/mixin/ItemStackMixin.java index 6557fc37..46a74c45 100644 --- a/src/main/java/com/bibireden/playerex/mixin/ItemStackMixin.java +++ b/src/main/java/com/bibireden/playerex/mixin/ItemStackMixin.java @@ -83,7 +83,7 @@ public void preventBreak(int amount, T entity, Consumer ItemStack stack = (ItemStack) (Object) this; if (stack.getItemHolder().is(PlayerEXTags.UNBREAKABLE_ITEMS)) { if (!PlayerEXUtil.isBroken(stack)) { - CompoundTag tag = stack.getTag(); + CompoundTag tag = stack.getOrCreateTag(); tag.putBoolean("broken", true); stack.setTag(tag); } @@ -97,7 +97,7 @@ public void removeBrokenOnRepair(int damage, CallbackInfo ci) { ItemStack stack = (ItemStack) (Object) this; if (PlayerEXUtil.isBroken(stack) && damage < stack.getDamageValue()) { - CompoundTag tag = stack.getTag(); + CompoundTag tag = stack.getOrCreateTag(); tag.putBoolean("broken", false); stack.setTag(tag); } @@ -114,8 +114,6 @@ public void modifyAttributeModifiers(EquipmentSlot slot, CallbackInfoReturnable< } if (PlayerEX.CONFIG.getArmorLevelingSettings().getEnabled() && PlayerEXUtil.isArmor(stack)) { PlayerEXUtil.addToModifier(hashmap, Attributes.ARMOR, getLevel() * PlayerEX.CONFIG.getArmorLevelingSettings().getArmorPerLevel()); - // TODO: % Damage reduction - // PlayerEXUtil.addToModifier(hashmap, , getLevel() * PlayerEX.CONFIG.getArmorLevelingSettings().getStatPerLevel()); } if (PlayerEXUtil.isBroken(stack)) { PlayerEXUtil.removeModifier(hashmap, Attributes.ARMOR); @@ -257,6 +255,11 @@ private int getXp() { return itemStack.getOrCreateTag().getInt("Experience"); } + @Unique + private double getReduction() { + return Math.min(getLevel() * PlayerEX.CONFIG.getArmorLevelingSettings().getReductionPerLevel(), 25d); + } + @Inject(method = "getTooltipLines", at = @At(value = "INVOKE", target = "Ljava/util/List;add(Ljava/lang/Object;)Z", ordinal = 0, shift = At.Shift.AFTER)) private void playerex$insertLevelTooltip( Player player, TooltipFlag context, @@ -269,4 +272,16 @@ private int getXp() { list.add(Component.translatable("playerex.item.experience", getXp(), PlayerEXUtil.getRequiredXpForNextLevel(itemStack))); } } + + @Inject(method = "getTooltipLines", at = @At(value = "INVOKE", target = "Ljava/util/List;add(Ljava/lang/Object;)Z", ordinal = 6, shift = At.Shift.AFTER)) + private void playerex$insertReductionTooltip( + Player player, TooltipFlag context, + CallbackInfoReturnable> info, + @Local List list + ) { + ItemStack itemStack = (ItemStack) (Object) this; + if (PlayerEXUtil.isArmor(itemStack)) { + list.add(Component.translatable("playerex.item.reduction", getReduction())); + } + } } diff --git a/src/main/java/com/bibireden/playerex/mixin/LivingEntityMixin.java b/src/main/java/com/bibireden/playerex/mixin/LivingEntityMixin.java index 21c39417..954d2927 100644 --- a/src/main/java/com/bibireden/playerex/mixin/LivingEntityMixin.java +++ b/src/main/java/com/bibireden/playerex/mixin/LivingEntityMixin.java @@ -7,6 +7,7 @@ import net.minecraft.world.InteractionHand; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.item.ItemStack; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; @@ -66,4 +67,19 @@ public void preventAttack(InteractionHand hand, CallbackInfo ci) { private boolean playerex$damage(boolean original, DamageSource source, float damage) { return LivingEntityEvents.SHOULD_DAMAGE.invoker().shouldDamage((LivingEntity) (Object) this, source, damage); } + + @ModifyReturnValue( + method = "getDamageAfterArmorAbsorb(Lnet/minecraft/world/damagesource/DamageSource;F)F", + at = @At("RETURN") + ) + public float applyDamageReduction(float original) { + LivingEntity self = (LivingEntity) (Object) this; + var total = 0d; + for (ItemStack slot : self.getArmorSlots()) { + total += Math.min(slot.getOrCreateTag().getInt("Level") * PlayerEX.CONFIG.getArmorLevelingSettings().getReductionPerLevel(), 25d); + } + // 400 because 4 slots then percentage to decimal + total /= 400; + return (float) (original * (1 - total)); + } } diff --git a/src/main/kotlin/com/bibireden/playerex/config/PlayerEXConfigModel.kt b/src/main/kotlin/com/bibireden/playerex/config/PlayerEXConfigModel.kt index 2914775a..79fed2e8 100644 --- a/src/main/kotlin/com/bibireden/playerex/config/PlayerEXConfigModel.kt +++ b/src/main/kotlin/com/bibireden/playerex/config/PlayerEXConfigModel.kt @@ -37,12 +37,9 @@ class PlayerEXConfigModel { @Sync(SyncMode.OVERRIDE_CLIENT) @JvmField + @RangeConstraint(min = 0.0, max = 25.0) var reductionPerLevel: Double = 1.0, - @Sync(SyncMode.OVERRIDE_CLIENT) - @JvmField - var maxReduction: Double = 1.0, - @Sync(SyncMode.OVERRIDE_CLIENT) @JvmField var formula: String = "5x^(1.1)", diff --git a/src/main/resources/assets/playerex/lang/en_us.json b/src/main/resources/assets/playerex/lang/en_us.json index 07d794fe..19526597 100644 --- a/src/main/resources/assets/playerex/lang/en_us.json +++ b/src/main/resources/assets/playerex/lang/en_us.json @@ -65,6 +65,7 @@ "attribute.name.playerex.wither_resistance": "Wither Resistance", "attribute.name.playerex.breaking_speed": "Breaking Speed", "attribute.name.playerex.focus": "Focus", + "attribute.name.playerex.percent_damage_reduction": "% Damage Reduction", "attribute.name.playerex.mining": "Mining", "attribute.name.playerex.enchanting": "Enchanting", @@ -90,6 +91,11 @@ {"index": 1, "color": "gold"} ], + "playerex.item.reduction": [ + {"index": 0, "color": "blue"}, + {"text": "% Damage Reduction", "color": "blue"} + ], + "playerex.command.reset_chunk": "Reset experience negation factor for chunk at %s", "playerex.command.refund": "Refunded %s skill points for player %s", @@ -228,12 +234,10 @@ "text.config.playerex-config.option.armorLevelingSettings.enabled": "Activated", "text.config.playerex-config.option.armorLevelingSettings.armorPerLevel": "Armor per Level", "text.config.playerex-config.option.armorLevelingSettings.reductionPerLevel": "% Damage Reduction per Level", - "text.config.playerex-config.option.armorLevelingSettings.maxReduction": "Maximum % Damage Reduction", "text.config.playerex-config.option.armorLevelingSettings.formula": "XP Formula", "text.config.playerex-config.option.armorLevelingSettings.xpFromPassive": "XP from Passive Mobs", "text.config.playerex-config.option.armorLevelingSettings.xpFromHostile": "XP from Hostile Mobs", "text.config.playerex-config.option.armorLevelingSettings.xpFromMiniboss": "XP from Minibosses (unused)", "text.config.playerex-config.option.armorLevelingSettings.xpFromBoss": "XP from Bosses", - "text.config.playerex-config.option.armorLevelingSettings.maxLevel": "Maximum Level", - "text.config.playerex-config.option.armorLevelingSettings.reduction": "Damage Reduction" + "text.config.playerex-config.option.armorLevelingSettings.maxLevel": "Maximum Level" } \ No newline at end of file diff --git a/src/main/resources/playerex.mixins.json b/src/main/resources/playerex.mixins.json index 04dfb44c..52aa7db6 100644 --- a/src/main/resources/playerex.mixins.json +++ b/src/main/resources/playerex.mixins.json @@ -6,10 +6,10 @@ "AbstractArrowMixin", "ExperienceOrbMixin", "InventoryMixin", + "ItemStackMixin", "LivingEntityMixin", "PlayerMixin", - "ServerPlayerMixin", - "ItemStackMixin" + "ServerPlayerMixin" ], "injectors": { "defaultRequire": 1 From 63b6932e67061797dcc97fb980838d17d8a52b32 Mon Sep 17 00:00:00 2001 From: Naomi Roberts Date: Fri, 13 Dec 2024 22:45:12 +0000 Subject: [PATCH 10/11] [feat] Items and weapons in loot tables can generate with a level - Range they can generate in is different based on dimension - Non-Vanilla dimensions follow the overworld range --- .../playerex/mixin/ItemStackMixin.java | 4 +- .../playerex/mixin/LivingEntityMixin.java | 2 +- .../kotlin/com/bibireden/playerex/PlayerEX.kt | 7 +- .../playerex/config/PlayerEXConfigModel.kt | 6 +- .../playerex/factory/EventFactory.kt | 21 +++++- .../playerex/predicate/FilterCheck.kt | 64 +++++++++++++++++++ 6 files changed, 98 insertions(+), 6 deletions(-) create mode 100644 src/main/kotlin/com/bibireden/playerex/predicate/FilterCheck.kt diff --git a/src/main/java/com/bibireden/playerex/mixin/ItemStackMixin.java b/src/main/java/com/bibireden/playerex/mixin/ItemStackMixin.java index 46a74c45..a7364e35 100644 --- a/src/main/java/com/bibireden/playerex/mixin/ItemStackMixin.java +++ b/src/main/java/com/bibireden/playerex/mixin/ItemStackMixin.java @@ -257,7 +257,7 @@ private int getXp() { @Unique private double getReduction() { - return Math.min(getLevel() * PlayerEX.CONFIG.getArmorLevelingSettings().getReductionPerLevel(), 25d); + return Math.min(getLevel() * PlayerEX.CONFIG.getArmorLevelingSettings().getReductionPerLevel(), PlayerEX.CONFIG.getArmorLevelingSettings().getMaxReduction()); } @Inject(method = "getTooltipLines", at = @At(value = "INVOKE", target = "Ljava/util/List;add(Ljava/lang/Object;)Z", ordinal = 0, shift = At.Shift.AFTER)) @@ -281,7 +281,7 @@ private double getReduction() { ) { ItemStack itemStack = (ItemStack) (Object) this; if (PlayerEXUtil.isArmor(itemStack)) { - list.add(Component.translatable("playerex.item.reduction", getReduction())); + list.add(Component.translatable("playerex.item.reduction", String.format("%.2f", getReduction()))); } } } diff --git a/src/main/java/com/bibireden/playerex/mixin/LivingEntityMixin.java b/src/main/java/com/bibireden/playerex/mixin/LivingEntityMixin.java index 954d2927..bfb24989 100644 --- a/src/main/java/com/bibireden/playerex/mixin/LivingEntityMixin.java +++ b/src/main/java/com/bibireden/playerex/mixin/LivingEntityMixin.java @@ -76,7 +76,7 @@ public float applyDamageReduction(float original) { LivingEntity self = (LivingEntity) (Object) this; var total = 0d; for (ItemStack slot : self.getArmorSlots()) { - total += Math.min(slot.getOrCreateTag().getInt("Level") * PlayerEX.CONFIG.getArmorLevelingSettings().getReductionPerLevel(), 25d); + total += Math.min(slot.getOrCreateTag().getInt("Level") * PlayerEX.CONFIG.getArmorLevelingSettings().getReductionPerLevel(), PlayerEX.CONFIG.getArmorLevelingSettings().getMaxReduction()); } // 400 because 4 slots then percentage to decimal total /= 400; diff --git a/src/main/kotlin/com/bibireden/playerex/PlayerEX.kt b/src/main/kotlin/com/bibireden/playerex/PlayerEX.kt index 639b0947..53522cac 100644 --- a/src/main/kotlin/com/bibireden/playerex/PlayerEX.kt +++ b/src/main/kotlin/com/bibireden/playerex/PlayerEX.kt @@ -12,7 +12,6 @@ import com.bibireden.playerex.api.event.LivingEntityEvents import com.bibireden.playerex.api.event.PlayerEXSoundEvents import com.bibireden.playerex.api.event.PlayerEntityEvents import com.bibireden.playerex.config.PlayerEXConfig -import com.bibireden.playerex.config.PlayerEXConfigModel import com.bibireden.playerex.config.PlayerEXConfigModel.Lifecycle import com.bibireden.playerex.ext.component import com.bibireden.playerex.factory.* @@ -20,12 +19,14 @@ import com.bibireden.playerex.networking.NetworkingChannels import com.bibireden.playerex.networking.NetworkingPackets import com.bibireden.playerex.networking.registerServerbound import com.bibireden.playerex.networking.types.UpdatePacketType +import com.bibireden.playerex.predicate.FilterCheck import de.dafuqs.additionalentityattributes.AdditionalEntityAttributes import eu.pb4.placeholders.api.Placeholders import net.fabricmc.api.ModInitializer import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback import net.fabricmc.fabric.api.entity.event.v1.ServerEntityCombatEvents import net.fabricmc.fabric.api.entity.event.v1.ServerPlayerEvents +import net.fabricmc.fabric.api.loot.v2.LootTableEvents import net.fabricmc.fabric.api.networking.v1.ServerLoginConnectionEvents import net.minecraft.core.Registry import net.minecraft.core.registries.BuiltInRegistries @@ -83,6 +84,8 @@ object PlayerEX : ModInitializer { LivingEntityEvents.ON_DAMAGE.register(EventFactory::onDamage) LivingEntityEvents.SHOULD_DAMAGE.register(EventFactory::shouldDamage) + LootTableEvents.MODIFY.register(EventFactory::onModifyLootTable) + PlayerEntityEvents.ON_CRITICAL.register(EventFactory::onCritAttack) PlayerEntityEvents.SHOULD_CRITICAL.register(EventFactory::attackIsCrit) @@ -97,6 +100,8 @@ object PlayerEX : ModInitializer { Registry.register(BuiltInRegistries.SOUND_EVENT, PlayerEXSoundEvents.SPEND_SOUND.location, PlayerEXSoundEvents.SPEND_SOUND) Registry.register(BuiltInRegistries.SOUND_EVENT, PlayerEXSoundEvents.REFUND_SOUND.location, PlayerEXSoundEvents.REFUND_SOUND) + Registry.register(BuiltInRegistries.LOOT_FUNCTION_TYPE, id("filtered"), FilterCheck.type()) + EntityAttributeModifiedEvents.MODIFIED.register { attribute, entity, _, _, _ -> if (entity?.level() == null) return@register // no entity & no world, skip diff --git a/src/main/kotlin/com/bibireden/playerex/config/PlayerEXConfigModel.kt b/src/main/kotlin/com/bibireden/playerex/config/PlayerEXConfigModel.kt index 79fed2e8..e4724215 100644 --- a/src/main/kotlin/com/bibireden/playerex/config/PlayerEXConfigModel.kt +++ b/src/main/kotlin/com/bibireden/playerex/config/PlayerEXConfigModel.kt @@ -35,10 +35,14 @@ class PlayerEXConfigModel { @JvmField var armorPerLevel: Double = 0.1, + @Sync(SyncMode.OVERRIDE_CLIENT) + @JvmField + var reductionPerLevel: Double = 0.1, + @Sync(SyncMode.OVERRIDE_CLIENT) @JvmField @RangeConstraint(min = 0.0, max = 25.0) - var reductionPerLevel: Double = 1.0, + var maxReduction: Double = 25.0, @Sync(SyncMode.OVERRIDE_CLIENT) @JvmField diff --git a/src/main/kotlin/com/bibireden/playerex/factory/EventFactory.kt b/src/main/kotlin/com/bibireden/playerex/factory/EventFactory.kt index 5c3ac8d3..fc2196e7 100644 --- a/src/main/kotlin/com/bibireden/playerex/factory/EventFactory.kt +++ b/src/main/kotlin/com/bibireden/playerex/factory/EventFactory.kt @@ -6,11 +6,15 @@ import com.bibireden.playerex.api.attribute.PlayerEXAttributes import com.bibireden.playerex.components.player.PlayerDataComponent import com.bibireden.playerex.config.PlayerEXConfig import com.bibireden.playerex.ext.component +import com.bibireden.playerex.predicate.FilterCheck import com.bibireden.playerex.registry.DamageModificationRegistry import com.bibireden.playerex.util.PlayerEXUtil +import net.fabricmc.fabric.api.loot.v2.LootTableSource import net.fabricmc.fabric.api.tag.convention.v1.ConventionalEntityTypeTags import net.minecraft.core.registries.BuiltInRegistries +import net.minecraft.resources.ResourceLocation import net.minecraft.server.level.ServerPlayer +import net.minecraft.server.packs.resources.ResourceManager import net.minecraft.world.damagesource.DamageSource import net.minecraft.world.effect.MobEffects import net.minecraft.world.entity.Entity @@ -20,6 +24,8 @@ import net.minecraft.world.entity.player.Player import net.minecraft.world.entity.projectile.AbstractArrow import net.minecraft.world.item.ItemStack import net.minecraft.world.level.Level +import net.minecraft.world.level.storage.loot.LootDataManager +import net.minecraft.world.level.storage.loot.LootTable object EventFactory { fun reset(oldPlayer: ServerPlayer, newPlayer: ServerPlayer, isAlive: Boolean) @@ -166,4 +172,17 @@ object EventFactory { }, maxLevel) } } -} \ No newline at end of file + + fun onModifyLootTable( + resourceManager: ResourceManager, + lootManager: LootDataManager, + id: ResourceLocation, + builder: LootTable.Builder, + source: LootTableSource + ) { + + builder.apply { + FilterCheck() + } + } +} diff --git a/src/main/kotlin/com/bibireden/playerex/predicate/FilterCheck.kt b/src/main/kotlin/com/bibireden/playerex/predicate/FilterCheck.kt new file mode 100644 index 00000000..f513ae7e --- /dev/null +++ b/src/main/kotlin/com/bibireden/playerex/predicate/FilterCheck.kt @@ -0,0 +1,64 @@ +package com.bibireden.playerex.predicate + +import com.bibireden.playerex.api.PlayerEXTags +import com.google.gson.JsonDeserializationContext +import com.google.gson.JsonObject +import com.google.gson.JsonSerializationContext +import net.minecraft.nbt.CompoundTag +import net.minecraft.world.item.ItemStack +import net.minecraft.world.level.Level +import net.minecraft.world.level.storage.loot.LootContext +import net.minecraft.world.level.storage.loot.Serializer +import net.minecraft.world.level.storage.loot.functions.LootItemFunction +import net.minecraft.world.level.storage.loot.functions.LootItemFunctionType +import kotlin.random.Random + +class FilterCheck : LootItemFunction { + override fun getType(): LootItemFunctionType? { + return type() + } + + override fun apply( + t: ItemStack?, + u: LootContext? + ): ItemStack? { + + // TODO: Random + val num = when (u?.level?.dimension()) { + Level.NETHER -> Random.nextInt(36, 71) + Level.END -> Random.nextInt(71, 105) + else -> Random.nextInt(1, 36) + } + + var tag = CompoundTag() + tag.putInt("Level", num) + + if(t?.`is`(PlayerEXTags.WEAPONS)!! || t.`is`(PlayerEXTags.ARMOR)) { + t.orCreateTag.merge(tag) + } + + return t + } + + class FilterSerializer : Serializer { + override fun serialize( + json: JsonObject, + value: FilterCheck, + serializationContext: JsonSerializationContext + ) { + } + + override fun deserialize( + json: JsonObject, + serializationContext: JsonDeserializationContext + ): FilterCheck? { + return FilterCheck() + } + } + + companion object { + fun type(): LootItemFunctionType { + return LootItemFunctionType(FilterSerializer()) + } + } +} \ No newline at end of file From 5eb28279c0669d56297e21d9e9526668a003edb4 Mon Sep 17 00:00:00 2001 From: Naomi Roberts Date: Fri, 13 Dec 2024 22:49:05 +0000 Subject: [PATCH 11/11] [fix] Remove TODO commment --- src/main/kotlin/com/bibireden/playerex/predicate/FilterCheck.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/kotlin/com/bibireden/playerex/predicate/FilterCheck.kt b/src/main/kotlin/com/bibireden/playerex/predicate/FilterCheck.kt index f513ae7e..fc530c4a 100644 --- a/src/main/kotlin/com/bibireden/playerex/predicate/FilterCheck.kt +++ b/src/main/kotlin/com/bibireden/playerex/predicate/FilterCheck.kt @@ -23,7 +23,6 @@ class FilterCheck : LootItemFunction { u: LootContext? ): ItemStack? { - // TODO: Random val num = when (u?.level?.dimension()) { Level.NETHER -> Random.nextInt(36, 71) Level.END -> Random.nextInt(71, 105)