From bc8f3fe5ec80bab9cbc6cf6abbf288668720d4c6 Mon Sep 17 00:00:00 2001 From: naomi Date: Tue, 30 Jul 2024 19:40:12 +0100 Subject: [PATCH 01/11] Migrate to Mojmap + Parchment (#17) * Migrate to Mojmap + Parchment * Attempt buildscript patch * Attempt buildscript fix v2 (manic) * CL adjustment honestly the CI was cobbled together --------- Co-authored-by: Bibi Reden --- .github/workflows/build-and-deploy.yml | 3 + CHANGELOG.md | 7 +- build.gradle | 14 +- gradle.properties | 8 +- .../playerex/mixin/EntityRendererMixin.java | 16 +- .../playerex/mixin/ItemStackMixin.java | 113 ++++++------- ...EntityMixin.java => LocalPlayerMixin.java} | 14 +- .../com/bibireden/playerex/PlayerEXClient.kt | 26 +-- .../bibireden/playerex/ui/PlayerEXScreen.kt | 42 ++--- .../ui/components/AttributeComponent.kt | 32 ++-- .../ui/components/AttributeListComponent.kt | 17 +- .../components/AttributeListEntryComponent.kt | 19 ++- .../playerex/ui/components/MenuComponent.kt | 10 +- .../buttons/AttributeButtonComponent.kt | 12 +- .../labels/AttributeLabelComponent.kt | 14 +- .../playerex/ui/menus/ConceptMenu.kt | 4 +- .../ui/menus/PlayerEXAttributesMenu.kt | 34 ++-- .../playerex/ui/util/FormattingPredicates.kt | 5 +- .../resources/playerex.client.mixins.json | 26 +-- .../playerex/mixin/AbstractArrowMixin.java | 79 ++++++++++ .../mixin/ExperienceOrbEntityMixin.java | 27 ---- .../playerex/mixin/ExperienceOrbMixin.java | 26 +++ ...nventoryMixin.java => InventoryMixin.java} | 12 +- .../playerex/mixin/LivingEntityMixin.java | 8 +- .../PersistentProjectileEntityMixin.java | 67 -------- ...layerEntityMixin.java => PlayerMixin.java} | 12 +- .../playerex/mixin/ServerLevelMixin.java | 7 + ...ntityMixin.java => ServerPlayerMixin.java} | 10 +- .../playerex/mixin/ServerWorldMixin.java | 7 - .../kotlin/com/bibireden/playerex/PlayerEX.kt | 27 ++-- .../bibireden/playerex/PlayerEXCommands.kt | 148 +++++++++--------- .../api/attribute/DefaultAttributeImpl.kt | 28 ++-- .../api/attribute/ModdedAttributes.kt | 6 +- .../api/attribute/PlayerEXAttributes.kt | 16 +- .../api/attribute/TradeSkillAttributes.kt | 4 +- .../playerex/api/damage/DamageFunction.kt | 4 +- .../playerex/api/damage/DamagePredicate.kt | 4 +- .../playerex/api/event/LivingEntityEvents.kt | 4 +- .../playerex/api/event/PlayerEXSoundEvents.kt | 8 +- .../playerex/api/event/PlayerEntityEvents.kt | 12 +- .../experience/ExperienceDataComponent.kt | 16 +- .../components/player/IPlayerDataComponent.kt | 24 +-- .../components/player/PlayerDataComponent.kt | 82 +++++----- .../bibireden/playerex/ext/EntityAttribute.kt | 10 +- .../bibireden/playerex/ext/PlayerEntity.kt | 8 +- .../playerex/factory/DamageFactory.kt | 22 +-- .../playerex/factory/EventFactory.kt | 56 +++---- .../playerex/factory/PlaceholderFactory.kt | 18 +-- .../playerex/factory/RefundFactory.kt | 4 +- .../factory/ServerNetworkingFactory.kt | 8 +- .../com/bibireden/playerex/keys/LevelKey.kt | 11 +- .../playerex/networking/NetworkingPackets.kt | 5 +- .../registry/RefundConditionRegistry.kt | 4 +- .../bibireden/playerex/util/PlayerEXUtil.kt | 6 +- src/main/resources/playerex.mixins.json | 28 ++-- 55 files changed, 624 insertions(+), 610 deletions(-) rename src/client/java/com/bibireden/playerex/mixin/{ClientPlayerEntityMixin.java => LocalPlayerMixin.java} (53%) create mode 100644 src/main/java/com/bibireden/playerex/mixin/AbstractArrowMixin.java delete mode 100644 src/main/java/com/bibireden/playerex/mixin/ExperienceOrbEntityMixin.java create mode 100644 src/main/java/com/bibireden/playerex/mixin/ExperienceOrbMixin.java rename src/main/java/com/bibireden/playerex/mixin/{PlayerInventoryMixin.java => InventoryMixin.java} (70%) delete mode 100644 src/main/java/com/bibireden/playerex/mixin/PersistentProjectileEntityMixin.java rename src/main/java/com/bibireden/playerex/mixin/{PlayerEntityMixin.java => PlayerMixin.java} (73%) create mode 100644 src/main/java/com/bibireden/playerex/mixin/ServerLevelMixin.java rename src/main/java/com/bibireden/playerex/mixin/{ServerPlayerEntityMixin.java => ServerPlayerMixin.java} (81%) delete mode 100644 src/main/java/com/bibireden/playerex/mixin/ServerWorldMixin.java diff --git a/.github/workflows/build-and-deploy.yml b/.github/workflows/build-and-deploy.yml index a37295da..57013c1c 100644 --- a/.github/workflows/build-and-deploy.yml +++ b/.github/workflows/build-and-deploy.yml @@ -3,6 +3,9 @@ on: push: branches-ignore: - master + - "**-dev" + - "**-dev**" + - dev jobs: build-and-deploy: diff --git a/CHANGELOG.md b/CHANGELOG.md index df6db1f3..970d80e9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,3 @@ -## Fixes ⚒️ -- Resolved spell power attribute addition to the proper percentage. -- Fixed some overlooked dependency issues with mc-publish. -- To use this, delete the previous (data-attributes) config folder (or change spell power based attribute addition in the functions from 0.0# to #.0) \ No newline at end of file +## Fixes & Changes ⚒️ +- Fixed issues with `alpha.5` having an outdated variant of the previous. +- Migrated to mojmappings. \ No newline at end of file diff --git a/build.gradle b/build.gradle index f61aa90a..9a24f981 100644 --- a/build.gradle +++ b/build.gradle @@ -35,6 +35,14 @@ repositories { 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 { @@ -51,7 +59,11 @@ loom { dependencies { minecraft "com.mojang:minecraft:${project.minecraft_version}" - mappings("net.fabricmc:yarn:${project.yarn_mappings}:v2") + 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}" diff --git a/gradle.properties b/gradle.properties index 72b36571..d9265d24 100644 --- a/gradle.properties +++ b/gradle.properties @@ -8,21 +8,23 @@ loader=fabric # Fabric Properties minecraft_version=1.20.1 -yarn_mappings=1.20.1+build.10 loader_version=0.15.11 fabric_kotlin_version=1.11.0+kotlin.2.0.0 loom_version=1.7-SNAPSHOT +# Mappings +parchment_version=1.20.1:2023.09.03 +quilt_mappings_version=23 # Mod Properties -mod_version=4.0.0-alpha.4+1.20.1 +mod_version=4.0.0-alpha.6+1.20.1 maven_group=com.bibireden.playerex archives_base_name=playerex-directors-cut # Dependencies fabric_version=0.92.2+1.20.1 cardinal_components_version=5.2.2 -additional_entity_attributes_version=1.7.4+1.20.0 +additional_entity_attributes_version=1.7.0+1.20.0 all_the_trims_version=3.4.2 placeholder_api_version=2.1.1+1.20 ranged_weapon_api_version=1.1.2+1.20.1 diff --git a/src/client/java/com/bibireden/playerex/mixin/EntityRendererMixin.java b/src/client/java/com/bibireden/playerex/mixin/EntityRendererMixin.java index fdb98573..993889bf 100644 --- a/src/client/java/com/bibireden/playerex/mixin/EntityRendererMixin.java +++ b/src/client/java/com/bibireden/playerex/mixin/EntityRendererMixin.java @@ -4,10 +4,10 @@ import com.bibireden.playerex.PlayerEX; import com.bibireden.playerex.api.attribute.PlayerEXAttributes; import com.llamalad7.mixinextras.sugar.Local; -import net.minecraft.client.render.entity.EntityRenderer; -import net.minecraft.entity.Entity; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.text.Text; +import net.minecraft.client.renderer.entity.EntityRenderer; +import net.minecraft.network.chat.Component; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.player.Player; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; @@ -20,12 +20,12 @@ abstract class EntityRendererMixin { @Unique private boolean playerex$shouldRenderLevel() { return PlayerEX.CONFIG.getShowLevelOnNameplates(); } - @ModifyArg(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/entity/EntityRenderer;renderLabelIfPresent(Lnet/minecraft/entity/Entity;Lnet/minecraft/text/Text;Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;I)V"), index = 1) - private Text playerex$renderLabelIfPresent(Text text, @Local(argsOnly = true) Entity entity) { - if (playerex$shouldRenderLevel() && entity instanceof PlayerEntity livingEntity) { + @ModifyArg(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/entity/EntityRenderer;renderNameTag(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/network/chat/Component;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;I)V"), index = 1) + private Component playerex$renderLabelIfPresent(Component text, @Local(argsOnly = true) Entity entity) { + if (playerex$shouldRenderLevel() && entity instanceof Player livingEntity) { Optional maybeLevel = DataAttributesAPI.getValue(PlayerEXAttributes.LEVEL, livingEntity); if (maybeLevel.isPresent()) { - text = text.copy().append(" ").append(Text.translatable("playerex.ui.nameplate.level", maybeLevel.get().intValue()).styled((style) -> style.withColor(0xFFAA00))); + text = text.copy().append(" ").append(Component.translatable("playerex.ui.nameplate.level", maybeLevel.get().intValue()).withStyle((style) -> style.withColor(0xFFAA00))); } } return text; diff --git a/src/client/java/com/bibireden/playerex/mixin/ItemStackMixin.java b/src/client/java/com/bibireden/playerex/mixin/ItemStackMixin.java index d5dbd95b..e09db198 100644 --- a/src/client/java/com/bibireden/playerex/mixin/ItemStackMixin.java +++ b/src/client/java/com/bibireden/playerex/mixin/ItemStackMixin.java @@ -4,17 +4,17 @@ import com.bibireden.playerex.PlayerEX; import com.bibireden.playerex.config.PlayerEXConfigModel; import com.google.common.collect.Multimap; -import net.minecraft.client.item.TooltipContext; -import net.minecraft.entity.EquipmentSlot; -import net.minecraft.entity.attribute.EntityAttribute; -import net.minecraft.entity.attribute.EntityAttributeInstance; -import net.minecraft.entity.attribute.EntityAttributeModifier; -import net.minecraft.entity.attribute.EntityAttributes; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.ItemStack; -import net.minecraft.text.MutableText; -import net.minecraft.text.Text; -import net.minecraft.util.Formatting; +import net.minecraft.ChatFormatting; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.world.entity.EquipmentSlot; +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.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.TooltipFlag; import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -32,58 +32,58 @@ @Mixin(ItemStack.class) abstract class ItemStackMixin { @Unique - private double playerex$modifyValue(double val, @Nullable PlayerEntity player, EntityAttribute attribute, UUID uuid) { + private double playerex$modifyValue(double val, @Nullable Player player, Attribute attribute, UUID uuid) { if (player == null || PlayerEX.CONFIG.getTooltip() == PlayerEXConfigModel.Tooltip.Default) return val; double valSubBase = val - player.getAttributeBaseValue(attribute); - EntityAttributeInstance instance = player.getAttributeInstance(attribute); + AttributeInstance instance = player.getAttribute(attribute); if (instance == null) return val; - EntityAttributeModifier modifier = instance.getModifier(uuid); + AttributeModifier modifier = instance.getModifier(uuid); double value = player.getAttributeValue(attribute) + valSubBase; - if (modifier != null) value -= modifier.getValue(); + if (modifier != null) value -= modifier.getAmount(); return PlayerEX.CONFIG.getTooltip() == PlayerEXConfigModel.Tooltip.Vanilla ? valSubBase : value; } @Unique - private String playerex$value(double e, Map.Entry entry, EntityAttributeModifier modifier) { - if (modifier.getOperation() != EntityAttributeModifier.Operation.ADDITION) return ItemStack.MODIFIER_FORMAT.format(e); - return ItemStack.MODIFIER_FORMAT.format(e); + private String playerex$value(double e, Map.Entry entry, AttributeModifier modifier) { + if (modifier.getOperation() != AttributeModifier.Operation.ADDITION) return ItemStack.ATTRIBUTE_MODIFIER_FORMAT.format(e); + return ItemStack.ATTRIBUTE_MODIFIER_FORMAT.format(e); } - @ModifyVariable(method = "getTooltip", at = @At(value = "STORE", ordinal = 1), ordinal = 0) - private double playerex$modifyAttackDamage(double original, PlayerEntity player) { - return playerex$modifyValue(original, player, EntityAttributes.GENERIC_ATTACK_DAMAGE, ItemFields.attackDamageModifierID()); + @ModifyVariable(method = "getTooltipLines", at = @At(value = "STORE", ordinal = 1), ordinal = 0) + private double playerex$modifyAttackDamage(double original, Player player) { + return playerex$modifyValue(original, player, Attributes.ATTACK_DAMAGE, ItemFields.attackDamageModifierID()); } - @ModifyVariable(method = "getTooltip", at = @At(value = "STORE", ordinal = 3), ordinal = 0) - private double playerex$modifyAttackSpeed(double original, PlayerEntity player) { - return playerex$modifyValue(original, player, EntityAttributes.GENERIC_ATTACK_SPEED, ItemFields.attackDamageModifierID()); + @ModifyVariable(method = "getTooltipLines", at = @At(value = "STORE", ordinal = 3), ordinal = 0) + private double playerex$modifyAttackSpeed(double original, Player player) { + return playerex$modifyValue(original, player, Attributes.ATTACK_SPEED, ItemFields.attackDamageModifierID()); } - @ModifyVariable(method = "getTooltip", at = @At(value = "STORE", ordinal = 1), ordinal = 0) + @ModifyVariable(method = "getTooltipLines", at = @At(value = "STORE", ordinal = 1), ordinal = 0) private boolean playerex$flagAttackDamage(boolean original) { return PlayerEX.CONFIG.getTooltip() != PlayerEXConfigModel.Tooltip.Vanilla && original; } - @ModifyVariable(method = "getTooltip", at = @At(value = "STORE", ordinal = 2), ordinal = 0) + @ModifyVariable(method = "getTooltipLines", at = @At(value = "STORE", ordinal = 2), ordinal = 0) private boolean playerex$flagAttackSpeed(boolean original) { return PlayerEX.CONFIG.getTooltip() != PlayerEXConfigModel.Tooltip.Vanilla && original; } - @ModifyVariable(method = "getTooltip", at = @At(value = "STORE", ordinal = 1), ordinal = 1) + @ModifyVariable(method = "getTooltipLines", at = @At(value = "STORE", ordinal = 1), ordinal = 1) private double playerex$modifyAdditionAttributeKnockback(double original) { return original / 10.0; } // todo: not sure about the implementation(s) here... - @Inject(method = "getTooltip", at = @At(value = "INVOKE", target = "Ljava/util/List;add(Ljava/lang/Object;)Z", ordinal = 7, shift = At.Shift.AFTER), locals = LocalCapture.CAPTURE_FAILHARD) + @Inject(method = "getTooltipLines", at = @At(value = "INVOKE", target = "Ljava/util/List;add(Ljava/lang/Object;)Z", ordinal = 7, shift = At.Shift.AFTER), locals = LocalCapture.CAPTURE_FAILHARD) private void playerex$insertModifierEqualsTooltip( - PlayerEntity player, TooltipContext context, - CallbackInfoReturnable> info, - List list, - MutableText arg3, + Player player, TooltipFlag context, + CallbackInfoReturnable> info, + List list, + MutableComponent arg3, int arg4, EquipmentSlot[] arg5, int arg6, @@ -91,58 +91,59 @@ abstract class ItemStackMixin { EquipmentSlot arg8, Multimap arg9, Iterator arg10, - Map.Entry entry, - EntityAttributeModifier entityAttributeModifier, + Map.Entry entry, + AttributeModifier entityAttributeModifier, double arg13, double e ) { - list.set(list.size() - 1, Text.literal(" ") - .append(Text.translatable("attribute.modifier.equals." + entityAttributeModifier.getOperation().getId(), playerex$value(e, entry, entityAttributeModifier), Text.translatable(entry.getKey().getTranslationKey()))) - .formatted(Formatting.DARK_GREEN) + list.set(list.size() - 1, Component.literal(" ") + .append(Component.translatable("attribute.modifier.equals." + entityAttributeModifier.getOperation().toValue(), playerex$value(e, entry, entityAttributeModifier), Component.translatable(entry.getKey().getDescriptionId()))) + .withStyle(ChatFormatting.DARK_GREEN) ); } - @Inject(method = "getTooltip", at = @At(value = "INVOKE", target = "Ljava/util/List;add(Ljava/lang/Object;)Z", ordinal = 8, shift = At.Shift.AFTER), locals = LocalCapture.CAPTURE_FAILHARD) + @Inject(method = "getTooltipLines", at = @At(value = "INVOKE", target = "Ljava/util/List;add(Ljava/lang/Object;)Z", ordinal = 8, shift = At.Shift.AFTER), locals = LocalCapture.CAPTURE_FAILHARD) private void playerex$insertModifierPlusTooltip( - PlayerEntity player, - TooltipContext context, - CallbackInfoReturnable> info, - List list, - MutableText arg3, + Player player, + TooltipFlag context, + CallbackInfoReturnable> info, + List list, + MutableComponent arg3, int arg4, EquipmentSlot[] arg5, int arg6, int arg7, EquipmentSlot arg8, Multimap arg9, Iterator arg10, - Map.Entry entry, EntityAttributeModifier entityAttributeModifier, + Map.Entry entry, AttributeModifier entityAttributeModifier, double arg13, double e ) { list.set( list.size() - 1, - Text.translatable("attribute.modifier.plus." + entityAttributeModifier.getOperation().getId(), + Component.translatable("attribute.modifier.plus." + entityAttributeModifier.getOperation().toValue(), playerex$value(e, entry, entityAttributeModifier), - Text.translatable(entry.getKey().getTranslationKey())).formatted(Formatting.BLUE) + Component.translatable(entry.getKey().getDescriptionId())).withStyle(ChatFormatting.BLUE) ); } - @Inject(method = "getTooltip", at = @At(value = "INVOKE", target = "Ljava/util/List;add(Ljava/lang/Object;)Z", ordinal = 9, shift = At.Shift.AFTER), locals = LocalCapture.CAPTURE_FAILHARD) + @Inject(method = "getTooltipLines", at = @At(value = "INVOKE", target = "Ljava/util/List;add(Ljava/lang/Object;)Z", ordinal = 9, shift = At.Shift.AFTER), locals = LocalCapture.CAPTURE_FAILHARD) private void playerex$insertModifierTakeTooltip( - PlayerEntity player, TooltipContext context, - CallbackInfoReturnable> info, - List list, - MutableText arg3, + Player player, TooltipFlag context, + CallbackInfoReturnable> info, + List list, + MutableComponent arg3, int arg4, EquipmentSlot[] arg5, - int arg6, int arg7, + int arg6, + int arg7, EquipmentSlot arg8, Multimap arg9, Iterator arg10, - Map.Entry entry, - EntityAttributeModifier entityAttributeModifier, + Map.Entry entry, + AttributeModifier entityAttributeModifier, double arg13, double e ) { list.set( list.size() - 1, - Text.translatable("attribute.modifier.take." + entityAttributeModifier.getOperation().getId(), + Component.translatable("attribute.modifier.take." + entityAttributeModifier.getOperation().toValue(), playerex$value(e, entry, entityAttributeModifier), - Text.translatable(entry.getKey().getTranslationKey())).formatted(Formatting.RED) + Component.translatable(entry.getKey().getDescriptionId())).withStyle(ChatFormatting.RED) ); } } diff --git a/src/client/java/com/bibireden/playerex/mixin/ClientPlayerEntityMixin.java b/src/client/java/com/bibireden/playerex/mixin/LocalPlayerMixin.java similarity index 53% rename from src/client/java/com/bibireden/playerex/mixin/ClientPlayerEntityMixin.java rename to src/client/java/com/bibireden/playerex/mixin/LocalPlayerMixin.java index e94a0aa9..b5872e8c 100644 --- a/src/client/java/com/bibireden/playerex/mixin/ClientPlayerEntityMixin.java +++ b/src/client/java/com/bibireden/playerex/mixin/LocalPlayerMixin.java @@ -1,8 +1,8 @@ package com.bibireden.playerex.mixin; import com.bibireden.playerex.ui.PlayerEXScreen; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.client.Minecraft; +import net.minecraft.client.player.LocalPlayer; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -10,12 +10,12 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -@Mixin(ClientPlayerEntity.class) -abstract class ClientPlayerEntityMixin { - @Shadow @Final protected MinecraftClient client; +@Mixin(LocalPlayer.class) +abstract class LocalPlayerMixin { + @Shadow @Final protected Minecraft minecraft; - @Inject(method = "setExperience", at = @At("TAIL")) + @Inject(method = "setExperienceValues", at = @At("TAIL")) private void setExperience(CallbackInfo ci) { - if (client.currentScreen instanceof PlayerEXScreen screen) screen.onExperienceUpdated(); + if (minecraft.screen instanceof PlayerEXScreen screen) screen.onExperienceUpdated(); } } diff --git a/src/client/kotlin/com/bibireden/playerex/PlayerEXClient.kt b/src/client/kotlin/com/bibireden/playerex/PlayerEXClient.kt index 8f260eae..73a684bd 100644 --- a/src/client/kotlin/com/bibireden/playerex/PlayerEXClient.kt +++ b/src/client/kotlin/com/bibireden/playerex/PlayerEXClient.kt @@ -11,34 +11,34 @@ import com.bibireden.playerex.networking.types.NotificationType import com.bibireden.playerex.registry.PlayerEXMenuRegistry import com.bibireden.playerex.ui.PlayerEXScreen import com.bibireden.playerex.ui.menus.PlayerEXAttributesMenu +import com.mojang.blaze3d.platform.InputConstants import net.fabricmc.api.ClientModInitializer import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper -import net.minecraft.client.MinecraftClient -import net.minecraft.client.network.ClientPlayerEntity -import net.minecraft.client.option.KeyBinding -import net.minecraft.client.util.InputUtil -import net.minecraft.sound.SoundCategory +import net.minecraft.client.KeyMapping +import net.minecraft.client.Minecraft +import net.minecraft.client.player.LocalPlayer +import net.minecraft.sounds.SoundSource import org.lwjgl.glfw.GLFW object PlayerEXClient : ClientModInitializer { val MAIN_UI_SCREEN_ID = PlayerEX.id("main_ui_model") - val KEYBINDING_MAIN_SCREEN: KeyBinding = KeyBindingHelper.registerKeyBinding(KeyBinding("${PlayerEX.MOD_ID}.key.main_screen", InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_MINUS, "key.categories.${PlayerEX.MOD_ID}")) + val KEYBINDING_MAIN_SCREEN: KeyMapping = KeyBindingHelper.registerKeyBinding(KeyMapping("${PlayerEX.MOD_ID}.key.main_screen", InputConstants.Type.KEYSYM, GLFW.GLFW_KEY_MINUS, "key.categories.${PlayerEX.MOD_ID}")) override fun onInitializeClient() { NetworkingChannels.NOTIFICATIONS.registerClientbound(NetworkingPackets.Notify::class) { (type), ctx -> val soundSettings = PlayerEX.CONFIG.soundSettings when (type) { - NotificationType.LevelUpAvailable -> ctx.player().playSound(PlayerEXSoundEvents.LEVEL_UP_SOUND, SoundCategory.NEUTRAL, soundSettings.levelUpVolume.toFloat(), 1F) - NotificationType.Spent -> ctx.player().playSound(PlayerEXSoundEvents.SPEND_SOUND, SoundCategory.NEUTRAL, soundSettings.skillUpVolume.toFloat(), 1F) - NotificationType.Refunded -> ctx.player().playSound(PlayerEXSoundEvents.REFUND_SOUND, SoundCategory.NEUTRAL, soundSettings.refundVolume.toFloat(), 0.7F) + NotificationType.LevelUpAvailable -> ctx.player().playNotifySound(PlayerEXSoundEvents.LEVEL_UP_SOUND, SoundSource.NEUTRAL, soundSettings.levelUpVolume.toFloat(), 1F) + NotificationType.Spent -> ctx.player().playNotifySound(PlayerEXSoundEvents.SPEND_SOUND, SoundSource.NEUTRAL, soundSettings.skillUpVolume.toFloat(), 1F) + NotificationType.Refunded -> ctx.player().playNotifySound(PlayerEXSoundEvents.REFUND_SOUND, SoundSource.NEUTRAL, soundSettings.refundVolume.toFloat(), 0.7F) } } EntityAttributeModifiedEvents.MODIFIED.register { attribute, entity, _, _, _ -> - if (entity is ClientPlayerEntity) { - val screen = MinecraftClient.getInstance().currentScreen + if (entity is LocalPlayer) { + val screen = Minecraft.getInstance().screen if (screen is PlayerEXScreen) { if (attribute == PlayerEXAttributes.LEVEL) { DataAttributesAPI.getValue(attribute, entity).map(Double::toInt).ifPresent(screen::onLevelUpdated) @@ -56,8 +56,8 @@ object PlayerEXClient : ClientModInitializer { ClientTickEvents.END_CLIENT_TICK.register { client -> if (PlayerEX.CONFIG.disableUI) return@register - while (KEYBINDING_MAIN_SCREEN.wasPressed()) { - if (client.currentScreen == null) { + while (KEYBINDING_MAIN_SCREEN.consumeClick()) { + if (client.screen == null) { client.setScreen(PlayerEXScreen()) } } diff --git a/src/client/kotlin/com/bibireden/playerex/ui/PlayerEXScreen.kt b/src/client/kotlin/com/bibireden/playerex/ui/PlayerEXScreen.kt index 31e98e63..65fe26eb 100644 --- a/src/client/kotlin/com/bibireden/playerex/ui/PlayerEXScreen.kt +++ b/src/client/kotlin/com/bibireden/playerex/ui/PlayerEXScreen.kt @@ -16,18 +16,18 @@ import com.bibireden.playerex.util.PlayerEXUtil import io.wispforest.owo.ui.base.BaseUIModelScreen import io.wispforest.owo.ui.component.* import io.wispforest.owo.ui.container.FlowLayout -import io.wispforest.owo.ui.core.Component +import io.wispforest.owo.ui.core.Component as OwoComponent import io.wispforest.owo.ui.core.Easing import io.wispforest.owo.ui.core.ParentComponent import io.wispforest.owo.ui.core.Sizing import io.wispforest.owo.util.EventSource -import net.minecraft.entity.attribute.EntityAttribute -import net.minecraft.text.Text -import net.minecraft.util.math.MathHelper +import net.minecraft.util.Mth +import net.minecraft.world.entity.ai.attributes.Attribute +import net.minecraft.network.chat.Component import kotlin.reflect.KClass // Transformers -fun ParentComponent.childById(clazz: KClass, id: String) = this.childById(clazz.java, id) +fun ParentComponent.childById(clazz: KClass, id: String) = this.childById(clazz.java, id) /** Primary screen for the mod that brings everything intended together. */ class PlayerEXScreen : BaseUIModelScreen(FlowLayout::class.java, DataSource.asset(PlayerEXClient.MAIN_UI_SCREEN_ID)) { @@ -35,7 +35,7 @@ class PlayerEXScreen : BaseUIModelScreen(FlowLayout::class.java, Dat private val pages: MutableList = mutableListOf() - private val player by lazy { this.client!!.player!! } + private val player by lazy { this.minecraft!!.player!! } private val content by lazy { uiAdapter.rootComponent.childById(FlowLayout::class, "content")!! } private val footer by lazy { uiAdapter.rootComponent.childById(FlowLayout::class, "footer")!! } @@ -45,14 +45,14 @@ class PlayerEXScreen : BaseUIModelScreen(FlowLayout::class.java, Dat private val onLevelUpdatedEvents = OnLevelUpdated.stream private val onLevelUpdated: EventSource = onLevelUpdatedEvents.source() - override fun shouldPause(): Boolean = false + override fun isPauseScreen(): Boolean = false /** Whenever the level attribute gets modified, and on initialization of the screen, this will be called. */ fun onLevelUpdated(level: Int) { val root = this.uiAdapter.rootComponent root.childById(LabelComponent::class, "level:current")?.apply { - text(Text.translatable("playerex.ui.current_level", player.level.toInt(), PlayerEXUtil.getRequiredXpForNextLevel(player))) + text(Component.translatable("playerex.ui.current_level", player.level.toInt(), PlayerEXUtil.getRequiredXpForNextLevel(player))) } updatePointsAvailable() @@ -66,7 +66,7 @@ class PlayerEXScreen : BaseUIModelScreen(FlowLayout::class.java, Dat } /** Whenever any attribute is updated, this will be called. */ - fun onAttributeUpdated(attribute: EntityAttribute, value: Double) { + fun onAttributeUpdated(attribute: Attribute, value: Double) { this.uiAdapter.rootComponent.forEachDescendant { descendant -> if (descendant is MenuComponent) descendant.onAttributeUpdatedEvents.sink().onAttributeUpdated(attribute, value) if (descendant is AttributeButtonComponent) descendant.refresh() @@ -76,8 +76,8 @@ class PlayerEXScreen : BaseUIModelScreen(FlowLayout::class.java, Dat private fun updatePointsAvailable() { this.uiAdapter.rootComponent.childById(LabelComponent::class, "points_available")?.apply { - text(Text.translatable("playerex.ui.main.skill_points_header").append(": [").append( - Text.literal("${player.data.skillPoints}").styled { + text(Component.translatable("playerex.ui.main.skill_points_header").append(": [").append( + Component.literal("${player.data.skillPoints}").withStyle { it.withColor(when (player.data.skillPoints) { 0 -> Colors.GRAY else -> Colors.SATURATED_BLUE }) @@ -91,32 +91,32 @@ class PlayerEXScreen : BaseUIModelScreen(FlowLayout::class.java, Dat val pageCounter = root.childById(LabelComponent::class, "counter")!! val content = root.childById(FlowLayout::class, "content")!! - pageCounter.text(Text.of("${currentPage + 1}/${pages.size}")) + pageCounter.text(Component.nullToEmpty("${currentPage + 1}/${pages.size}")) content.clearChildren() content.child(pages[currentPage]) } private fun updateLevelUpButton() { - val amount = levelAmount.text.toIntOrNull() ?: return + val amount = levelAmount.value.toIntOrNull() ?: return val result = player.level + amount this.uiAdapter.rootComponent.childById(ButtonComponent::class, "level:button")!! .active(player.experienceLevel >= PlayerEXUtil.getRequiredXpForLevel(player, result)) - .tooltip(Text.translatable("playerex.ui.level_button", PlayerEXUtil.getRequiredXpForLevel(player, result), amount, player.experienceLevel)) + .tooltip(Component.translatable("playerex.ui.level_button", PlayerEXUtil.getRequiredXpForLevel(player, result), amount, player.experienceLevel)) } private fun updateProgressBar() { var result = 0.0 if (player.experienceLevel > 0) { val required = PlayerEXUtil.getRequiredXpForNextLevel(player) - result = MathHelper.clamp((player.experienceLevel.toDouble() / required) * 100, 0.0, 100.0) + result = Mth.clamp((player.experienceLevel.toDouble() / required) * 100, 0.0, 100.0) } footer.childById(BoxComponent::class, "progress")!! .horizontalSizing().animate(1000, Easing.CUBIC, Sizing.fill(result.toInt())).forwards() } override fun build(rootComponent: FlowLayout) { - val player = client?.player ?: return + val player = minecraft?.player ?: return val levelUpButton = rootComponent.childById(ButtonComponent::class, "level:button")!! @@ -137,7 +137,7 @@ class PlayerEXScreen : BaseUIModelScreen(FlowLayout::class.java, Dat this.onLevelUpdated(player.level.toInt()) this.onPagesUpdated() - pageCounter.text(Text.of("${currentPage + 1}/${pages.size}")) + pageCounter.text(Component.nullToEmpty("${currentPage + 1}/${pages.size}")) content.clearChildren() content.child(pages[currentPage]) @@ -156,12 +156,12 @@ class PlayerEXScreen : BaseUIModelScreen(FlowLayout::class.java, Dat } levelUpButton.onPress { - levelAmount.text.toIntOrNull()?.let { NetworkingChannels.MODIFY.clientHandle().send(NetworkingPackets.Level(it)) } + levelAmount.value.toIntOrNull()?.let { NetworkingChannels.MODIFY.clientHandle().send(NetworkingPackets.Level(it)) } } onLevelUpdated.subscribe { this.updateLevelUpButton() } - exit.onPress { this.close() } + exit.onPress { this.onClose() } } /** Whenever the player's experience is changed, refreshing the current status of experience-tied ui elements. */ @@ -171,8 +171,8 @@ class PlayerEXScreen : BaseUIModelScreen(FlowLayout::class.java, Dat } override fun keyPressed(keyCode: Int, scanCode: Int, modifiers: Int): Boolean { - if (PlayerEXClient.KEYBINDING_MAIN_SCREEN.matchesKey(keyCode, scanCode)) { - this.close() + if (PlayerEXClient.KEYBINDING_MAIN_SCREEN.matches(keyCode, scanCode)) { + this.onClose() return true } return super.keyPressed(keyCode, scanCode, modifiers) diff --git a/src/client/kotlin/com/bibireden/playerex/ui/components/AttributeComponent.kt b/src/client/kotlin/com/bibireden/playerex/ui/components/AttributeComponent.kt index eb07d100..faaa5bcb 100644 --- a/src/client/kotlin/com/bibireden/playerex/ui/components/AttributeComponent.kt +++ b/src/client/kotlin/com/bibireden/playerex/ui/components/AttributeComponent.kt @@ -1,7 +1,5 @@ package com.bibireden.playerex.ui.components -import com.bibireden.data_attributes.DataAttributes -import com.bibireden.data_attributes.DataAttributesClient import com.bibireden.data_attributes.api.DataAttributesAPI import com.bibireden.data_attributes.api.attribute.EntityAttributeSupplier import com.bibireden.data_attributes.api.attribute.IEntityAttribute @@ -16,41 +14,41 @@ import com.bibireden.playerex.ui.util.Colors import io.wispforest.owo.ui.component.Components import io.wispforest.owo.ui.container.FlowLayout import io.wispforest.owo.ui.core.* -import net.minecraft.entity.attribute.EntityAttribute -import net.minecraft.entity.player.PlayerEntity -import net.minecraft.text.Style -import net.minecraft.text.Text -import net.minecraft.util.Formatting +import net.minecraft.ChatFormatting +import net.minecraft.network.chat.Style +import net.minecraft.world.entity.ai.attributes.Attribute +import net.minecraft.world.entity.player.Player import kotlin.jvm.optionals.getOrNull +import net.minecraft.network.chat.Component private val StackingBehavior.symbol: String get() = if (this == StackingBehavior.Add) "+" else "×" -class AttributeComponent(private val attribute: EntityAttribute, private val player: PlayerEntity, component: IPlayerDataComponent) : FlowLayout(Sizing.fill(100), Sizing.fixed(18), Algorithm.HORIZONTAL) { +class AttributeComponent(private val attribute: Attribute, private val player: Player, component: IPlayerDataComponent) : FlowLayout(Sizing.fill(100), Sizing.fixed(18), Algorithm.HORIZONTAL) { val label: AttributeLabelComponent fun refresh() { val entries = DataAttributesAPI.clientManager.data.functions[attribute.id] if (!entries.isNullOrEmpty()) { label.tooltip( - Text.translatable("playerex.ui.main.modified_attributes").also { text -> + Component.translatable("playerex.ui.main.modified_attributes").also { text -> text.append("\n") - text.append(Text.literal(attribute.id.toString()).formatted(Formatting.DARK_GRAY)) + text.append(Component.literal(attribute.id.toString()).withStyle(ChatFormatting.DARK_GRAY)) text.append("\n\n") entries.forEach { function -> val childAttribute = EntityAttributeSupplier(function.id).get().getOrNull() ?: return@forEach val formula = (childAttribute as IEntityAttribute).`data_attributes$formula`() text.apply { - append(Text.translatable(childAttribute.translationKey).styled { it.withColor(Colors.SATURATED_BLUE) }) + append(Component.translatable(childAttribute.descriptionId).withStyle { it.withColor(Colors.SATURATED_BLUE) }) append(" (") - append(Text.literal(function.behavior.symbol).styled { it.withColor(Colors.DARK_GREEN) }) - append(Text.literal("${function.value}")) - append(Text.literal(":").fillStyle(Style.EMPTY.withColor(Colors.DARK_GRAY))) - append(Text.literal(formula.name.lowercase()).styled { it.withColor(if (formula == StackingFormula.Flat) Colors.SANDY else Colors.IMPISH_RED) }) + append(Component.literal(function.behavior.symbol).withStyle { it.withColor(Colors.DARK_GREEN) }) + append(Component.literal("${function.value}")) + append(Component.literal(":").withStyle(Style.EMPTY.withColor(Colors.DARK_GRAY))) + append(Component.literal(formula.name.lowercase()).withStyle { it.withColor(if (formula == StackingFormula.Flat) Colors.SANDY else Colors.IMPISH_RED) }) append(")") val decLength = function.value.toString().substringAfter('.').length - append(Text.literal(" (%.${decLength}f)\n".format(DataAttributesAPI.getValue(childAttribute, player).orElse(0.0))).formatted(Formatting.GRAY)) + append(Component.literal(" (%.${decLength}f)\n".format(DataAttributesAPI.getValue(childAttribute, player).orElse(0.0))).withStyle(ChatFormatting.GRAY)) } } } @@ -60,7 +58,7 @@ class AttributeComponent(private val attribute: EntityAttribute, private val pla init { child( - Components.label(Text.translatable(attribute.translationKey)) + Components.label(Component.translatable(attribute.descriptionId)) .verticalTextAlignment(VerticalAlignment.CENTER) .sizing(Sizing.content(), Sizing.fill(100)) .positioning(Positioning.relative(0, 50)) diff --git a/src/client/kotlin/com/bibireden/playerex/ui/components/AttributeListComponent.kt b/src/client/kotlin/com/bibireden/playerex/ui/components/AttributeListComponent.kt index 140fd881..9bb8468e 100644 --- a/src/client/kotlin/com/bibireden/playerex/ui/components/AttributeListComponent.kt +++ b/src/client/kotlin/com/bibireden/playerex/ui/components/AttributeListComponent.kt @@ -1,31 +1,28 @@ package com.bibireden.playerex.ui.components import com.bibireden.data_attributes.api.attribute.EntityAttributeSupplier -import com.bibireden.playerex.ui.util.FormattingPredicates import io.wispforest.owo.ui.component.Components import io.wispforest.owo.ui.container.Containers import io.wispforest.owo.ui.container.FlowLayout -import io.wispforest.owo.ui.core.Insets -import io.wispforest.owo.ui.core.Positioning import io.wispforest.owo.ui.core.Sizing -import net.minecraft.entity.attribute.EntityAttribute -import net.minecraft.entity.player.PlayerEntity -import net.minecraft.text.Text +import net.minecraft.world.entity.ai.attributes.Attribute +import net.minecraft.world.entity.player.Player +import net.minecraft.network.chat.Component -private fun transform(array: List>): List> { - val filtered = mutableListOf>() +private fun transform(array: List>): List> { + val filtered = mutableListOf>() for ((attribute, pred) in array) { if (attribute.get().isPresent) filtered.add(Pair(attribute.get().get(), pred)) } return filtered } -class AttributeListComponent(translationKey: String, private val player: PlayerEntity, private val gimmie: List>) : FlowLayout(Sizing.fill(25), Sizing.content(), Algorithm.VERTICAL) { +class AttributeListComponent(translationKey: String, private val player: Player, private val gimmie: List>) : FlowLayout(Sizing.fill(25), Sizing.content(), Algorithm.VERTICAL) { val entriesSection: FlowLayout init { child( - Components.label(Text.translatable(translationKey)) + Components.label(Component.translatable(translationKey)) .horizontalSizing(Sizing.fill(100)) ) child(Components.box(Sizing.fill(100), Sizing.fixed(2))) diff --git a/src/client/kotlin/com/bibireden/playerex/ui/components/AttributeListEntryComponent.kt b/src/client/kotlin/com/bibireden/playerex/ui/components/AttributeListEntryComponent.kt index 1ce45b69..a9e125db 100644 --- a/src/client/kotlin/com/bibireden/playerex/ui/components/AttributeListEntryComponent.kt +++ b/src/client/kotlin/com/bibireden/playerex/ui/components/AttributeListEntryComponent.kt @@ -1,22 +1,21 @@ package com.bibireden.playerex.ui.components import com.bibireden.data_attributes.api.DataAttributesAPI -import com.bibireden.playerex.ext.id import com.bibireden.playerex.ui.util.Colors import io.wispforest.owo.ui.component.LabelComponent import io.wispforest.owo.ui.core.HorizontalAlignment import io.wispforest.owo.ui.core.VerticalAlignment -import net.minecraft.entity.attribute.EntityAttribute -import net.minecraft.entity.player.PlayerEntity -import net.minecraft.text.Text +import net.minecraft.world.entity.ai.attributes.Attribute +import net.minecraft.world.entity.player.Player +import net.minecraft.network.chat.Component typealias FormattingPredicate = (Double) -> String class AttributeListEntryComponent( - val attribute: EntityAttribute, - val player: PlayerEntity, + val attribute: Attribute, + val player: Player, private val formattingPredicate: FormattingPredicate -) : LabelComponent(Text.empty()) { +) : LabelComponent(Component.empty()) { init { horizontalTextAlignment(HorizontalAlignment.CENTER) verticalTextAlignment(VerticalAlignment.CENTER) @@ -26,11 +25,11 @@ class AttributeListEntryComponent( fun refresh() { text( - Text.translatable(attribute.translationKey) + Component.translatable(attribute.descriptionId) .append(": ") - .append(Text.literal( + .append(Component.literal( DataAttributesAPI.getValue(attribute, player).map { formattingPredicate(it) } - .orElse("N/A")).styled { it.withColor(Colors.GOLD) } + .orElse("N/A")).withStyle { it.withColor(Colors.GOLD) } ) ) } diff --git a/src/client/kotlin/com/bibireden/playerex/ui/components/MenuComponent.kt b/src/client/kotlin/com/bibireden/playerex/ui/components/MenuComponent.kt index afaa4222..5f766354 100644 --- a/src/client/kotlin/com/bibireden/playerex/ui/components/MenuComponent.kt +++ b/src/client/kotlin/com/bibireden/playerex/ui/components/MenuComponent.kt @@ -7,10 +7,8 @@ import io.wispforest.owo.ui.core.OwoUIAdapter import io.wispforest.owo.ui.core.Sizing import io.wispforest.owo.util.EventSource import io.wispforest.owo.util.EventStream -import net.minecraft.client.MinecraftClient -import net.minecraft.client.gui.screen.Screen -import net.minecraft.client.network.ClientPlayerEntity -import net.minecraft.entity.attribute.EntityAttribute +import net.minecraft.client.player.LocalPlayer +import net.minecraft.world.entity.ai.attributes.Attribute import org.jetbrains.annotations.ApiStatus /** @@ -28,7 +26,7 @@ abstract class MenuComponent(horizontalSizing: Sizing = Sizing.fill(100), vertic val onAttributeUpdated: EventSource = onAttributeUpdatedEvents.source() /** When the [PlayerEXScreen] is ready to be constructed, this function (if the component is registered) will be called.*/ - abstract fun build(player: ClientPlayerEntity, adapter: OwoUIAdapter, component: IPlayerDataComponent) + abstract fun build(player: LocalPlayer, adapter: OwoUIAdapter, component: IPlayerDataComponent) fun interface OnLevelUpdated { fun onLevelUpdated(level: Int) @@ -41,7 +39,7 @@ abstract class MenuComponent(horizontalSizing: Sizing = Sizing.fill(100), vertic } fun interface OnAttributeUpdated { - fun onAttributeUpdated(attribute: EntityAttribute, level: Double) + fun onAttributeUpdated(attribute: Attribute, level: Double) companion object { val stream: EventStream get() = EventStream { subscribers -> diff --git a/src/client/kotlin/com/bibireden/playerex/ui/components/buttons/AttributeButtonComponent.kt b/src/client/kotlin/com/bibireden/playerex/ui/components/buttons/AttributeButtonComponent.kt index b18e2c94..b98d7f79 100644 --- a/src/client/kotlin/com/bibireden/playerex/ui/components/buttons/AttributeButtonComponent.kt +++ b/src/client/kotlin/com/bibireden/playerex/ui/components/buttons/AttributeButtonComponent.kt @@ -11,16 +11,16 @@ import com.bibireden.playerex.ui.childById import io.wispforest.owo.ui.component.ButtonComponent import io.wispforest.owo.ui.component.TextBoxComponent import io.wispforest.owo.ui.core.Sizing -import net.minecraft.entity.attribute.EntityAttribute -import net.minecraft.entity.player.PlayerEntity -import net.minecraft.text.Text +import net.minecraft.world.entity.ai.attributes.Attribute +import net.minecraft.world.entity.player.Player +import net.minecraft.network.chat.Component -class AttributeButtonComponent(val attribute: EntityAttribute, private val player: PlayerEntity, private val component: IPlayerDataComponent, val type: PlayerEXScreen.AttributeButtonComponentType) : ButtonComponent( - Text.literal(type.symbol), +class AttributeButtonComponent(val attribute: Attribute, private val player: Player, private val component: IPlayerDataComponent, val type: PlayerEXScreen.AttributeButtonComponentType) : ButtonComponent( + Component.literal(type.symbol), { // reference text-box to get needed value to send to server it.parent()?.parent()?.childById(TextBoxComponent::class, "input")?.let { box -> - val amount = box.text.toDoubleOrNull() ?: return@let + val amount = box.value.toDoubleOrNull() ?: return@let val points = type.getPointsFromComponent(component) if (points < amount) return@let // invalid, not enough points. diff --git a/src/client/kotlin/com/bibireden/playerex/ui/components/labels/AttributeLabelComponent.kt b/src/client/kotlin/com/bibireden/playerex/ui/components/labels/AttributeLabelComponent.kt index f3974aa0..d9c13978 100644 --- a/src/client/kotlin/com/bibireden/playerex/ui/components/labels/AttributeLabelComponent.kt +++ b/src/client/kotlin/com/bibireden/playerex/ui/components/labels/AttributeLabelComponent.kt @@ -6,20 +6,18 @@ import com.bibireden.playerex.ext.id import com.bibireden.playerex.ui.util.Colors import io.wispforest.owo.ui.component.LabelComponent import io.wispforest.owo.ui.core.HorizontalAlignment -import io.wispforest.owo.ui.core.Sizing import io.wispforest.owo.ui.core.VerticalAlignment -import net.minecraft.entity.attribute.EntityAttribute -import net.minecraft.entity.player.PlayerEntity -import net.minecraft.text.Text -import net.minecraft.util.Formatting +import net.minecraft.world.entity.ai.attributes.Attribute +import net.minecraft.world.entity.player.Player +import net.minecraft.network.chat.Component -private fun createTextFromAttribute(attribute: EntityAttribute, player: PlayerEntity) = Text.literal("(") - .append(Text.literal("${DataAttributesAPI.getValue(attribute, player).map(Double::toInt).orElse(0)}").styled { +private fun createTextFromAttribute(attribute: Attribute, player: Player) = Component.literal("(") + .append(Component.literal("${DataAttributesAPI.getValue(attribute, player).map(Double::toInt).orElse(0)}").withStyle { it.withColor(Colors.GOLD) }) .append("/${(attribute as IEntityAttribute).`data_attributes$max`().toInt()})") -open class AttributeLabelComponent(private val attribute: EntityAttribute, private val player: PlayerEntity) : LabelComponent(Text.empty()) { +open class AttributeLabelComponent(private val attribute: Attribute, private val player: Player) : LabelComponent(Component.empty()) { init { this.horizontalTextAlignment(HorizontalAlignment.CENTER) this.verticalTextAlignment(VerticalAlignment.CENTER) diff --git a/src/client/kotlin/com/bibireden/playerex/ui/menus/ConceptMenu.kt b/src/client/kotlin/com/bibireden/playerex/ui/menus/ConceptMenu.kt index 47b212a0..71d09e9d 100644 --- a/src/client/kotlin/com/bibireden/playerex/ui/menus/ConceptMenu.kt +++ b/src/client/kotlin/com/bibireden/playerex/ui/menus/ConceptMenu.kt @@ -4,11 +4,11 @@ import com.bibireden.playerex.components.player.IPlayerDataComponent import com.bibireden.playerex.ui.components.MenuComponent import io.wispforest.owo.ui.container.FlowLayout import io.wispforest.owo.ui.core.OwoUIAdapter -import net.minecraft.client.network.ClientPlayerEntity +import net.minecraft.client.player.LocalPlayer import org.jetbrains.annotations.ApiStatus @ApiStatus.Internal class ConceptMenu : MenuComponent(algorithm = Algorithm.VERTICAL) { - override fun build(player: ClientPlayerEntity, adapter: OwoUIAdapter, component: IPlayerDataComponent) { + override fun build(player: LocalPlayer, adapter: OwoUIAdapter, component: IPlayerDataComponent) { } } \ No newline at end of file diff --git a/src/client/kotlin/com/bibireden/playerex/ui/menus/PlayerEXAttributesMenu.kt b/src/client/kotlin/com/bibireden/playerex/ui/menus/PlayerEXAttributesMenu.kt index e8273422..def9eb03 100644 --- a/src/client/kotlin/com/bibireden/playerex/ui/menus/PlayerEXAttributesMenu.kt +++ b/src/client/kotlin/com/bibireden/playerex/ui/menus/PlayerEXAttributesMenu.kt @@ -20,11 +20,11 @@ import io.wispforest.owo.ui.container.Containers import io.wispforest.owo.ui.container.FlowLayout import io.wispforest.owo.ui.core.* import net.fabric_extras.ranged_weapon.api.EntityAttributes_RangedWeapon -import net.minecraft.client.network.ClientPlayerEntity -import net.minecraft.entity.attribute.EntityAttributes -import net.minecraft.entity.player.PlayerEntity -import net.minecraft.registry.Registries -import net.minecraft.text.Text +import net.minecraft.client.player.LocalPlayer +import net.minecraft.core.registries.BuiltInRegistries +import net.minecraft.world.entity.ai.attributes.Attributes +import net.minecraft.world.entity.player.Player +import net.minecraft.network.chat.Component import org.jetbrains.annotations.ApiStatus // todo: cache buttons/certain UI elements @@ -32,10 +32,10 @@ import org.jetbrains.annotations.ApiStatus @ApiStatus.Internal class PlayerEXAttributesMenu : MenuComponent(algorithm = Algorithm.HORIZONTAL) { private val MELEE_COMBAT_STATS: List> = listOf( - EntityAttributeSupplier(EntityAttributes.GENERIC_ATTACK_DAMAGE.id) to FormattingPredicates.NORMAL, - EntityAttributeSupplier(EntityAttributes.GENERIC_ATTACK_SPEED.id) to FormattingPredicates.NORMAL, + EntityAttributeSupplier(Attributes.ATTACK_DAMAGE.id) to FormattingPredicates.NORMAL, + EntityAttributeSupplier(Attributes.ATTACK_SPEED.id) to FormattingPredicates.NORMAL, EntityAttributeSupplier(PlayerEXAttributes.MELEE_CRITICAL_DAMAGE.id) to FormattingPredicates.PERCENTAGE_MULTIPLY, - EntityAttributeSupplier(PlayerEXAttributes.MELEE_CRITICAL_CHANCE.id) to FormattingPredicates.PERCENTAGE_MULTIPLY, + EntityAttributeSupplier(PlayerEXAttributes.MELEE_CRITICAL_CHANCE.id) to FormattingPredicates.PERCENTAGE_MULTIPLY ) private val RANGED_COMBAT_STATS: List> = listOf( @@ -46,10 +46,10 @@ class PlayerEXAttributesMenu : MenuComponent(algorithm = Algorithm.HORIZONTAL) { ) private val DEFENSE_COMBAT_STATS: List> = listOf( - EntityAttributeSupplier(EntityAttributes.GENERIC_ARMOR.id) to FormattingPredicates.NORMAL, + EntityAttributeSupplier(Attributes.ARMOR.id) to FormattingPredicates.NORMAL, EntityAttributeSupplier(AdditionalEntityAttributes.MAGIC_PROTECTION.id) to FormattingPredicates.NORMAL, - EntityAttributeSupplier(EntityAttributes.GENERIC_ARMOR_TOUGHNESS.id) to FormattingPredicates.NORMAL, - EntityAttributeSupplier(EntityAttributes.GENERIC_KNOCKBACK_RESISTANCE.id) to FormattingPredicates.PERCENTAGE_DIVIDE, + EntityAttributeSupplier(Attributes.ARMOR_TOUGHNESS.id) to FormattingPredicates.NORMAL, + EntityAttributeSupplier(Attributes.KNOCKBACK_RESISTANCE.id) to FormattingPredicates.PERCENTAGE_DIVIDE, EntityAttributeSupplier(PlayerEXAttributes.EVASION.id) to FormattingPredicates.PERCENTAGE_MULTIPLY, ) @@ -57,7 +57,7 @@ class PlayerEXAttributesMenu : MenuComponent(algorithm = Algorithm.HORIZONTAL) { EntityAttributeSupplier(PlayerEXAttributes.HEALTH_REGENERATION.id) to FormattingPredicates.PERCENTAGE_MULTIPLY, EntityAttributeSupplier(PlayerEXAttributes.HEAL_AMPLIFICATION.id) to FormattingPredicates.PERCENTAGE_MULTIPLY, EntityAttributeSupplier(PlayerEXAttributes.LIFESTEAL.id) to FormattingPredicates.PERCENTAGE_MULTIPLY, - EntityAttributeSupplier(EntityAttributes.GENERIC_MOVEMENT_SPEED.id) to FormattingPredicates.NORMAL, + EntityAttributeSupplier(Attributes.MOVEMENT_SPEED.id) to FormattingPredicates.NORMAL, ) private val RESISTANCE_STATS: List> = listOf( @@ -89,9 +89,9 @@ class PlayerEXAttributesMenu : MenuComponent(algorithm = Algorithm.HORIZONTAL) { } } - private fun onInputFieldUpdated(player: PlayerEntity, component: IPlayerDataComponent) { + private fun onInputFieldUpdated(player: Player, component: IPlayerDataComponent) { this.childById(FlowLayout::class, "attributes")?.childById(TextBoxComponent::class, "input")?.also { - val result = it.text.toDoubleOrNull() ?: return@also + val result = it.value.toDoubleOrNull() ?: return@also this.forEachDescendant { descendant -> if (descendant is AttributeButtonComponent) { val max = (descendant.attribute as IEntityAttribute).`data_attributes$max`() @@ -106,13 +106,13 @@ class PlayerEXAttributesMenu : MenuComponent(algorithm = Algorithm.HORIZONTAL) { } - override fun build(player: ClientPlayerEntity, adapter: OwoUIAdapter, component: IPlayerDataComponent) { + override fun build(player: LocalPlayer, adapter: OwoUIAdapter, component: IPlayerDataComponent) { child(Containers.verticalScroll( Sizing.fill(45), Sizing.fill(100), Containers.verticalFlow(Sizing.fill(100), Sizing.content()).apply { child(Containers.horizontalFlow(Sizing.fill(100), Sizing.content(2)).apply { - child(Components.label(Text.translatable("playerex.ui.category.primary_attributes"))) + child(Components.label(Component.translatable("playerex.ui.category.primary_attributes"))) child( Components.textBox(Sizing.fixed(27)) .also { @@ -129,7 +129,7 @@ class PlayerEXAttributesMenu : MenuComponent(algorithm = Algorithm.HORIZONTAL) { verticalAlignment(VerticalAlignment.TOP) gap(5) padding(Insets.right(5)) - children(PlayerEXAttributes.PRIMARY_ATTRIBUTE_IDS.mapNotNull(Registries.ATTRIBUTE::get).map { AttributeComponent(it, player, component) }) + children(PlayerEXAttributes.PRIMARY_ATTRIBUTE_IDS.mapNotNull(BuiltInRegistries.ATTRIBUTE::get).map { AttributeComponent(it, player, component) }) }.id("attributes")) ) child(Containers.verticalScroll( diff --git a/src/client/kotlin/com/bibireden/playerex/ui/util/FormattingPredicates.kt b/src/client/kotlin/com/bibireden/playerex/ui/util/FormattingPredicates.kt index 06d59ae7..12f6d487 100644 --- a/src/client/kotlin/com/bibireden/playerex/ui/util/FormattingPredicates.kt +++ b/src/client/kotlin/com/bibireden/playerex/ui/util/FormattingPredicates.kt @@ -1,8 +1,7 @@ package com.bibireden.playerex.ui.util -import com.bibireden.data_attributes.ext.round import com.bibireden.playerex.ui.components.FormattingPredicate -import net.minecraft.entity.attribute.EntityAttribute +import net.minecraft.world.entity.ai.attributes.Attribute import kotlin.math.round object FormattingPredicates { @@ -11,7 +10,7 @@ object FormattingPredicates { val PERCENTAGE_MULTIPLY: FormattingPredicate = { "${(it * 100.0).toInt()}%" } val PERCENTAGE_DIVIDE: FormattingPredicate = { "${(it / 100.0).toInt()}%" } - fun fromBaseValue(attribute: EntityAttribute): FormattingPredicate { + fun fromBaseValue(attribute: Attribute): FormattingPredicate { return { val result = round(it - attribute.defaultValue).toInt() var text = "$result" diff --git a/src/client/resources/playerex.client.mixins.json b/src/client/resources/playerex.client.mixins.json index 896e6187..8b401a8f 100644 --- a/src/client/resources/playerex.client.mixins.json +++ b/src/client/resources/playerex.client.mixins.json @@ -1,15 +1,15 @@ { - "required": true, - "package": "com.bibireden.playerex.mixin", - "compatibilityLevel": "JAVA_17", - "client": [ - "ClientPlayerEntityMixin", - "EntityRendererMixin" - ], - "injectors": { - "defaultRequire": 1 - }, - "mixins": [ - "ItemStackMixin" - ] + "required": true, + "package": "com.bibireden.playerex.mixin", + "compatibilityLevel": "JAVA_17", + "client": [ + "EntityRendererMixin", + "LocalPlayerMixin" + ], + "injectors": { + "defaultRequire": 1 + }, + "mixins": [ + "ItemStackMixin" + ] } \ No newline at end of file diff --git a/src/main/java/com/bibireden/playerex/mixin/AbstractArrowMixin.java b/src/main/java/com/bibireden/playerex/mixin/AbstractArrowMixin.java new file mode 100644 index 00000000..00086ff6 --- /dev/null +++ b/src/main/java/com/bibireden/playerex/mixin/AbstractArrowMixin.java @@ -0,0 +1,79 @@ +package com.bibireden.playerex.mixin; + +import com.bibireden.data_attributes.api.DataAttributesAPI; +import com.bibireden.playerex.api.attribute.PlayerEXAttributes; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.projectile.AbstractArrow; +import net.minecraft.world.entity.projectile.Projectile; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.EntityHitResult; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.ModifyArg; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.Optional; + +@Mixin(AbstractArrow.class) +public abstract class AbstractArrowMixin extends Projectile { + @Shadow public abstract void setCritArrow(boolean critical); + + // Constructor for the mixin class + private AbstractArrowMixin(EntityType entityType, Level level) { + super(entityType, level); + } + + @SuppressWarnings("UnreachableCode") + @Inject(method = "onHitEntity", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/projectile/AbstractArrow;isCritArrow()Z")) + private void playerex_onEntityHit(EntityHitResult entityHitResult, CallbackInfo info) { + AbstractArrow projectileEntity = (AbstractArrow) (Object) this; + Entity entity = projectileEntity.getOwner(); + + if (entity instanceof LivingEntity) { + + Optional rangedCritChanceOptional = DataAttributesAPI.getValue(PlayerEXAttributes.RANGED_CRITICAL_CHANCE, (LivingEntity) entity); + + if (rangedCritChanceOptional.isPresent()) { + projectileEntity.setCritArrow(false); + } + if (this.getOwner() instanceof LivingEntity owner) { + DataAttributesAPI.getValue(PlayerEXAttributes.RANGED_CRITICAL_CHANCE, owner).ifPresent((chance) -> this.setCritArrow(false)); + } + } + } + + @SuppressWarnings("UnreachableCode") + @ModifyArg(method = "onHitEntity", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;hurt(Lnet/minecraft/world/damagesource/DamageSource;F)Z")) + private float playerex_onEntityHit(float i) { + AbstractArrow projectileEntity = (AbstractArrow)(Object) this; + Entity owner = projectileEntity.getOwner(); + double damage = i; + + if(owner instanceof LivingEntity livingEntity) { + final double amount = damage; + + Optional rangedCritOptional = DataAttributesAPI.getValue(PlayerEXAttributes.RANGED_CRITICAL_CHANCE, livingEntity); + + if (rangedCritOptional.isPresent()) + { + boolean cache = livingEntity.getRandom().nextFloat() < rangedCritOptional.get(); + projectileEntity.setCritArrow(cache); + + if (cache) + { + Optional rangedCritDamageOptional = DataAttributesAPI.getValue(PlayerEXAttributes.RANGED_CRITICAL_DAMAGE, livingEntity); + if (rangedCritOptional.isPresent()) + { + damage = amount * (1.0 + (10.0 * rangedCritDamageOptional.get())); + } + } + } + } + + return (float) damage; + } +} diff --git a/src/main/java/com/bibireden/playerex/mixin/ExperienceOrbEntityMixin.java b/src/main/java/com/bibireden/playerex/mixin/ExperienceOrbEntityMixin.java deleted file mode 100644 index 24979cff..00000000 --- a/src/main/java/com/bibireden/playerex/mixin/ExperienceOrbEntityMixin.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.bibireden.playerex.mixin; - -import com.bibireden.playerex.PlayerEX; -import com.bibireden.playerex.components.PlayerEXComponents; -import net.minecraft.entity.Entity; -import net.minecraft.entity.ExperienceOrbEntity; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; -import net.minecraft.world.chunk.Chunk; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -@Mixin(ExperienceOrbEntity.class) -public abstract class ExperienceOrbEntityMixin { - @Inject(method = "(Lnet/minecraft/world/World;DDDI)V", at = @At("TAIL")) - private void playerex$init(World world, double x, double y, double z, int amount, CallbackInfo ci) { - BlockPos pos = BlockPos.ofFloored(x, y, z); - Chunk chunk = world.getChunk(pos); - PlayerEXComponents.EXPERIENCE_DATA.maybeGet(chunk).ifPresent(data -> { - if (data.updateExperienceNegationFactor(amount)) { - ((ExperienceOrbEntity) (Object) this).remove(Entity.RemovalReason.DISCARDED); - } - }); - } -} diff --git a/src/main/java/com/bibireden/playerex/mixin/ExperienceOrbMixin.java b/src/main/java/com/bibireden/playerex/mixin/ExperienceOrbMixin.java new file mode 100644 index 00000000..0ad1b1e9 --- /dev/null +++ b/src/main/java/com/bibireden/playerex/mixin/ExperienceOrbMixin.java @@ -0,0 +1,26 @@ +package com.bibireden.playerex.mixin; + +import com.bibireden.playerex.components.PlayerEXComponents; +import net.minecraft.core.BlockPos; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.ExperienceOrb; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.chunk.ChunkAccess; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(ExperienceOrb.class) +public abstract class ExperienceOrbMixin { + @Inject(method = "(Lnet/minecraft/world/level/Level;DDDI)V", at = @At("TAIL")) + private void playerex$init(Level world, double x, double y, double z, int amount, CallbackInfo ci) { + BlockPos pos = BlockPos.containing(x, y, z); + ChunkAccess chunk = world.getChunk(pos); + PlayerEXComponents.EXPERIENCE_DATA.maybeGet(chunk).ifPresent(data -> { + if (data.updateExperienceNegationFactor(amount)) { + ((ExperienceOrb) (Object) this).remove(Entity.RemovalReason.DISCARDED); + } + }); + } +} diff --git a/src/main/java/com/bibireden/playerex/mixin/PlayerInventoryMixin.java b/src/main/java/com/bibireden/playerex/mixin/InventoryMixin.java similarity index 70% rename from src/main/java/com/bibireden/playerex/mixin/PlayerInventoryMixin.java rename to src/main/java/com/bibireden/playerex/mixin/InventoryMixin.java index c8bbcd50..6e802bab 100644 --- a/src/main/java/com/bibireden/playerex/mixin/PlayerInventoryMixin.java +++ b/src/main/java/com/bibireden/playerex/mixin/InventoryMixin.java @@ -3,8 +3,8 @@ import com.bibireden.data_attributes.api.DataAttributesAPI; import com.bibireden.playerex.api.attribute.PlayerEXAttributes; import com.llamalad7.mixinextras.injector.ModifyReturnValue; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.entity.player.Player; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -12,11 +12,11 @@ import java.util.Optional; -@Mixin(PlayerInventory.class) -public abstract class PlayerInventoryMixin { - @Shadow @Final public PlayerEntity player; +@Mixin(Inventory.class) +public abstract class InventoryMixin { + @Shadow @Final public Player player; - @ModifyReturnValue(method = "getBlockBreakingSpeed", at = @At("RETURN")) + @ModifyReturnValue(method = "getDestroySpeed", at = @At("RETURN")) private float playerex$getBlockBreakingSpeed(float original) { Optional maybeBreakingSpeed = DataAttributesAPI.INSTANCE.getValue(PlayerEXAttributes.BREAKING_SPEED, this.player); return maybeBreakingSpeed.map(v -> original + v.floatValue() - 1.0F).orElse(original); diff --git a/src/main/java/com/bibireden/playerex/mixin/LivingEntityMixin.java b/src/main/java/com/bibireden/playerex/mixin/LivingEntityMixin.java index 3e50b0e5..cd5a99bd 100644 --- a/src/main/java/com/bibireden/playerex/mixin/LivingEntityMixin.java +++ b/src/main/java/com/bibireden/playerex/mixin/LivingEntityMixin.java @@ -2,8 +2,8 @@ import com.bibireden.playerex.api.event.LivingEntityEvents; import com.llamalad7.mixinextras.injector.ModifyReturnValue; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.damage.DamageSource; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.LivingEntity; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; @@ -42,12 +42,12 @@ public abstract class LivingEntityMixin { } } - @ModifyVariable(method = "damage", at = @At("HEAD"), ordinal = 0, argsOnly = true) + @ModifyVariable(method = "hurt", at = @At("HEAD"), ordinal = 0, argsOnly = true) private float playerex$damage(float original, DamageSource source) { return LivingEntityEvents.ON_DAMAGE.invoker().onDamage((LivingEntity) (Object) this, source, original); } - @ModifyReturnValue(method = "damage", at = @At("RETURN")) + @ModifyReturnValue(method = "hurt", at = @At("RETURN")) private boolean playerex$damage(boolean original, DamageSource source, float damage) { boolean cancelled = LivingEntityEvents.SHOULD_DAMAGE.invoker().shouldDamage((LivingEntity) (Object) this, source, damage); return cancelled && original; diff --git a/src/main/java/com/bibireden/playerex/mixin/PersistentProjectileEntityMixin.java b/src/main/java/com/bibireden/playerex/mixin/PersistentProjectileEntityMixin.java deleted file mode 100644 index 542dde5c..00000000 --- a/src/main/java/com/bibireden/playerex/mixin/PersistentProjectileEntityMixin.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.bibireden.playerex.mixin; - -import com.bibireden.data_attributes.api.DataAttributesAPI; -import com.bibireden.playerex.api.attribute.PlayerEXAttributes; -import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityType; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.projectile.PersistentProjectileEntity; -import net.minecraft.entity.projectile.ProjectileEntity; -import net.minecraft.util.hit.EntityHitResult; -import net.minecraft.world.World; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.ModifyArg; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import java.util.Optional; - -@Mixin(PersistentProjectileEntity.class) -public abstract class PersistentProjectileEntityMixin extends ProjectileEntity { - @Shadow public abstract void setCritical(boolean critical); - - // Constructor for the mixin class - private PersistentProjectileEntityMixin(EntityType entityType, World world) { - super(entityType, world); - } - - @Inject(method = "onEntityHit", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/projectile/PersistentProjectileEntity;isCritical()Z")) - private void playerex_onEntityHit(EntityHitResult entityHitResult, CallbackInfo info) { - if (this.getOwner() instanceof LivingEntity owner) { - DataAttributesAPI.getValue(PlayerEXAttributes.RANGED_CRITICAL_CHANCE, owner).ifPresent((chance) -> this.setCritical(false)); - } - } - - @SuppressWarnings("UnreachableCode") - @ModifyArg(method = "onEntityHit", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;damage(Lnet/minecraft/entity/damage/DamageSource;F)Z")) - private float playerex_onEntityHit(float i) { - PersistentProjectileEntity persistentProjectileEntity = (PersistentProjectileEntity)(Object) this; - Entity owner = persistentProjectileEntity.getOwner(); - double damage = i; - - if(owner instanceof LivingEntity livingEntity) { - final double amount = damage; - - Optional rangedCritOptional = DataAttributesAPI.getValue(PlayerEXAttributes.RANGED_CRITICAL_CHANCE, livingEntity); - - if (rangedCritOptional.isPresent()) - { - boolean cache = livingEntity.getRandom().nextFloat() < rangedCritOptional.get(); - persistentProjectileEntity.setCritical(cache); - - if (cache) - { - Optional rangedCritDamageOptional = DataAttributesAPI.getValue(PlayerEXAttributes.RANGED_CRITICAL_DAMAGE, livingEntity); - if (rangedCritOptional.isPresent()) - { - damage = amount * (1.0 + (10.0 * rangedCritDamageOptional.get())); - } - } - } - } - - return (float) damage; - } -} diff --git a/src/main/java/com/bibireden/playerex/mixin/PlayerEntityMixin.java b/src/main/java/com/bibireden/playerex/mixin/PlayerMixin.java similarity index 73% rename from src/main/java/com/bibireden/playerex/mixin/PlayerEntityMixin.java rename to src/main/java/com/bibireden/playerex/mixin/PlayerMixin.java index b4dec88f..12874428 100644 --- a/src/main/java/com/bibireden/playerex/mixin/PlayerEntityMixin.java +++ b/src/main/java/com/bibireden/playerex/mixin/PlayerMixin.java @@ -1,22 +1,22 @@ package com.bibireden.playerex.mixin; import com.bibireden.playerex.api.event.PlayerEntityEvents; -import net.minecraft.entity.Entity; -import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.player.Player; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.ModifyVariable; -@Mixin(PlayerEntity.class) -public abstract class PlayerEntityMixin { +@Mixin(Player.class) +public abstract class PlayerMixin { @ModifyVariable(method = "attack", at = @At("STORE"), name = "bl3", ordinal = 2) private boolean playerex_attack(boolean bl3, Entity target) { - return PlayerEntityEvents.SHOULD_CRITICAL.invoker().shouldCritical((PlayerEntity)(Object) this, target, bl3); + return PlayerEntityEvents.SHOULD_CRITICAL.invoker().shouldCritical((Player)(Object) this, target, bl3); } @ModifyVariable(method = "attack", at = @At(value = "STORE", ordinal = 2), name = "f", ordinal = 0) private float playerex_attack(float f, Entity target) { - return PlayerEntityEvents.ON_CRITICAL.invoker().onCriticalDamage((PlayerEntity) (Object) this, target, f); + return PlayerEntityEvents.ON_CRITICAL.invoker().onCriticalDamage((Player) (Object) this, target, f); } } diff --git a/src/main/java/com/bibireden/playerex/mixin/ServerLevelMixin.java b/src/main/java/com/bibireden/playerex/mixin/ServerLevelMixin.java new file mode 100644 index 00000000..a4ac9874 --- /dev/null +++ b/src/main/java/com/bibireden/playerex/mixin/ServerLevelMixin.java @@ -0,0 +1,7 @@ +package com.bibireden.playerex.mixin; + +import net.minecraft.server.level.ServerLevel; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(ServerLevel.class) +public abstract class ServerLevelMixin {} diff --git a/src/main/java/com/bibireden/playerex/mixin/ServerPlayerEntityMixin.java b/src/main/java/com/bibireden/playerex/mixin/ServerPlayerMixin.java similarity index 81% rename from src/main/java/com/bibireden/playerex/mixin/ServerPlayerEntityMixin.java rename to src/main/java/com/bibireden/playerex/mixin/ServerPlayerMixin.java index a80b30a4..53de7062 100644 --- a/src/main/java/com/bibireden/playerex/mixin/ServerPlayerEntityMixin.java +++ b/src/main/java/com/bibireden/playerex/mixin/ServerPlayerMixin.java @@ -5,18 +5,18 @@ import com.bibireden.playerex.factory.ServerNetworkingFactory; import com.bibireden.playerex.networking.types.NotificationType; import com.bibireden.playerex.util.PlayerEXUtil; -import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.server.level.ServerPlayer; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @SuppressWarnings("UnreachableCode") -@Mixin(ServerPlayerEntity.class) -public abstract class ServerPlayerEntityMixin { - @Inject(method = "addExperienceLevels", at = @At("TAIL")) +@Mixin(ServerPlayer.class) +public abstract class ServerPlayerMixin { + @Inject(method = "giveExperienceLevels", at = @At("TAIL")) private void addExperienceLevels(int levels, CallbackInfo ci) { - ServerPlayerEntity player = (ServerPlayerEntity) (Object) this; + ServerPlayer player = (ServerPlayer) (Object) this; PlayerDataComponent component = (PlayerDataComponent) PlayerEXComponents.PLAYER_DATA.get(player); int current = player.experienceLevel; diff --git a/src/main/java/com/bibireden/playerex/mixin/ServerWorldMixin.java b/src/main/java/com/bibireden/playerex/mixin/ServerWorldMixin.java deleted file mode 100644 index d4045db0..00000000 --- a/src/main/java/com/bibireden/playerex/mixin/ServerWorldMixin.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.bibireden.playerex.mixin; - -import net.minecraft.server.world.ServerWorld; -import org.spongepowered.asm.mixin.Mixin; - -@Mixin(ServerWorld.class) -public abstract class ServerWorldMixin {} diff --git a/src/main/kotlin/com/bibireden/playerex/PlayerEX.kt b/src/main/kotlin/com/bibireden/playerex/PlayerEX.kt index 2886dca1..b5c8aa47 100644 --- a/src/main/kotlin/com/bibireden/playerex/PlayerEX.kt +++ b/src/main/kotlin/com/bibireden/playerex/PlayerEX.kt @@ -21,11 +21,10 @@ import net.fabricmc.api.ModInitializer import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback import net.fabricmc.fabric.api.entity.event.v1.ServerPlayerEvents import net.fabricmc.fabric.api.networking.v1.ServerLoginConnectionEvents -import net.minecraft.entity.attribute.EntityAttributes -import net.minecraft.registry.Registries -import net.minecraft.registry.Registry -import net.minecraft.util.Identifier -import net.minecraft.util.math.MathHelper +import net.minecraft.core.Registry +import net.minecraft.core.registries.BuiltInRegistries +import net.minecraft.resources.ResourceLocation +import net.minecraft.world.entity.ai.attributes.Attributes import org.slf4j.LoggerFactory object PlayerEX : ModInitializer { @@ -37,7 +36,7 @@ object PlayerEX : ModInitializer { @JvmField val CONFIG = PlayerEXConfig.createAndLoad() - fun id(path: String) = Identifier.of(MOD_ID, path)!! + fun id(path: String) = ResourceLocation.tryBuild(MOD_ID, path)!! private val gimmick = listOf( "Let's do it right this time...", @@ -77,23 +76,23 @@ object PlayerEX : ModInitializer { PlaceholderFactory.STORE.forEach(Placeholders::register) - Registry.register(Registries.SOUND_EVENT, PlayerEXSoundEvents.LEVEL_UP_SOUND.id, PlayerEXSoundEvents.LEVEL_UP_SOUND) - Registry.register(Registries.SOUND_EVENT, PlayerEXSoundEvents.SPEND_SOUND.id, PlayerEXSoundEvents.SPEND_SOUND) - Registry.register(Registries.SOUND_EVENT, PlayerEXSoundEvents.REFUND_SOUND.id, PlayerEXSoundEvents.REFUND_SOUND) + Registry.register(BuiltInRegistries.SOUND_EVENT, PlayerEXSoundEvents.LEVEL_UP_SOUND.location, PlayerEXSoundEvents.LEVEL_UP_SOUND) + Registry.register(BuiltInRegistries.SOUND_EVENT, PlayerEXSoundEvents.SPEND_SOUND.location, PlayerEXSoundEvents.SPEND_SOUND) + Registry.register(BuiltInRegistries.SOUND_EVENT, PlayerEXSoundEvents.REFUND_SOUND.location, PlayerEXSoundEvents.REFUND_SOUND) DefaultAttributeFactory.registerOverrides(DefaultAttributeImpl.OVERRIDES) DefaultAttributeFactory.registerFunctions(DefaultAttributeImpl.FUNCTIONS) DefaultAttributeFactory.registerEntityTypes(DefaultAttributeImpl.ENTITY_TYPES) EntityAttributeModifiedEvents.MODIFIED.register { attribute, entity, _, _, _ -> - if (entity?.world == null) return@register // no entity & no world, skip + if (entity?.level() == null) return@register // no entity & no world, skip - if (!entity.world.isClient) { - if (attribute == EntityAttributes.GENERIC_MAX_HEALTH) { - entity.health = attribute.clamp(entity.health.toDouble()).toFloat() + if (!entity.level().isClientSide()) { + if (attribute == Attributes.MAX_HEALTH) { + entity.health = attribute.sanitizeValue(entity.health.toDouble()).toFloat() } else if (attribute == AdditionalEntityAttributes.LUNG_CAPACITY) { - entity.air = attribute.clamp(entity.air.toDouble()).toInt() + entity.airSupply = attribute.sanitizeValue(entity.airSupply.toDouble()).toInt() } } } diff --git a/src/main/kotlin/com/bibireden/playerex/PlayerEXCommands.kt b/src/main/kotlin/com/bibireden/playerex/PlayerEXCommands.kt index 60ad3270..c163d29c 100644 --- a/src/main/kotlin/com/bibireden/playerex/PlayerEXCommands.kt +++ b/src/main/kotlin/com/bibireden/playerex/PlayerEXCommands.kt @@ -13,78 +13,78 @@ import com.mojang.brigadier.builder.RequiredArgumentBuilder import com.mojang.brigadier.context.CommandContext import com.mojang.brigadier.suggestion.SuggestionProvider import net.fabricmc.fabric.api.networking.v1.PlayerLookup -import net.minecraft.command.CommandRegistryAccess -import net.minecraft.command.CommandSource -import net.minecraft.command.EntitySelector -import net.minecraft.command.argument.EntityArgumentType -import net.minecraft.command.argument.IdentifierArgumentType -import net.minecraft.entity.attribute.EntityAttribute -import net.minecraft.entity.player.PlayerEntity -import net.minecraft.server.command.CommandManager -import net.minecraft.server.command.CommandManager.RegistrationEnvironment -import net.minecraft.server.command.ServerCommandSource -import net.minecraft.text.MutableText -import net.minecraft.text.Text -import net.minecraft.util.Identifier -import net.minecraft.util.math.MathHelper - -private typealias Context = CommandContext +import net.minecraft.commands.CommandBuildContext +import net.minecraft.commands.CommandSourceStack +import net.minecraft.commands.Commands +import net.minecraft.commands.Commands.CommandSelection +import net.minecraft.commands.SharedSuggestionProvider +import net.minecraft.commands.arguments.EntityArgument +import net.minecraft.commands.arguments.ResourceLocationArgument +import net.minecraft.commands.arguments.selector.EntitySelector +import net.minecraft.network.chat.Component +import net.minecraft.network.chat.MutableComponent +import net.minecraft.resources.ResourceLocation +import net.minecraft.util.Mth +import net.minecraft.world.entity.ai.attributes.Attribute +import net.minecraft.world.entity.player.Player + +private typealias Context = CommandContext object PlayerEXCommands { - private val MODIFIABLE_ATTRIBUTES_SUGGESTIONS = SuggestionProvider { _, builder -> - CommandSource.suggestIdentifiers(PlayerEXAttributes.PRIMARY_ATTRIBUTE_IDS, builder) - CommandSource.suggestIdentifiers(TradeSkillAttributes.IDS, builder) + private val MODIFIABLE_ATTRIBUTES_SUGGESTIONS = SuggestionProvider { _, builder -> + SharedSuggestionProvider.suggestResource(PlayerEXAttributes.PRIMARY_ATTRIBUTE_IDS, builder) + SharedSuggestionProvider.suggestResource(TradeSkillAttributes.IDS, builder) } - private val playerArgument: RequiredArgumentBuilder - get() = CommandManager.argument("player", EntityArgumentType.player()) + private val playerArgument: RequiredArgumentBuilder + get() = Commands.argument("player", EntityArgument.player()) - private val amountArgument: RequiredArgumentBuilder - get() = CommandManager.argument("amount", IntegerArgumentType.integer()) + private val amountArgument: RequiredArgumentBuilder + get() = Commands.argument("amount", IntegerArgumentType.integer()) - private val identifierArgument: RequiredArgumentBuilder - get() = CommandManager.argument("id", IdentifierArgumentType.identifier()) + private val identifierArgument: RequiredArgumentBuilder + get() = Commands.argument("id", ResourceLocationArgument.id()) - fun register(dispatcher: CommandDispatcher, access: CommandRegistryAccess, environment: RegistrationEnvironment) { - dispatcher.register(CommandManager.literal("playerex") + fun register(dispatcher: CommandDispatcher, ctx: CommandBuildContext, selection: CommandSelection) { + dispatcher.register(Commands.literal("playerex") .requires(::isOp) - .then(CommandManager.literal("level") - .then(CommandManager.literal("get").then(playerArgument.executes(::executeLevelGetCommand))) - .then(CommandManager.literal("add").then( + .then(Commands.literal("level") + .then(Commands.literal("get").then(playerArgument.executes(::executeLevelGetCommand))) + .then(Commands.literal("add").then( playerArgument.executes(::executeLevelUpCommand) .then(amountArgument.executes { executeLevelUpCommand(it, IntegerArgumentType.getInteger(it, "amount")) }) ) ) ) - .then(CommandManager.literal("reset") + .then(Commands.literal("reset") .then(playerArgument.executes(::executeResetCommand) - .then(CommandManager.argument("retain", IntegerArgumentType.integer(0, 100)).executes { executeResetCommand(it, IntegerArgumentType.getInteger(it, "retain")) }) + .then(Commands.argument("retain", IntegerArgumentType.integer(0, 100)).executes { executeResetCommand(it, IntegerArgumentType.getInteger(it, "retain")) }) ) - .then(CommandManager.literal("@all").executes(::executeResetAllCommand) + .then(Commands.literal("@all").executes(::executeResetAllCommand) .then(amountArgument.executes { executeResetAllCommand(it, IntegerArgumentType.getInteger(it, "amount")) }) ) ) - .then(CommandManager.literal("skill") + .then(Commands.literal("skill") .then(identifierArgument.suggests(MODIFIABLE_ATTRIBUTES_SUGGESTIONS) - .then(CommandManager.literal("get").then(playerArgument.executes(::executeSkillGetCommand))) - .then(CommandManager.literal("add") + .then(Commands.literal("get").then(playerArgument.executes(::executeSkillGetCommand))) + .then(Commands.literal("add") .then(playerArgument .executes(::executeSkillUpCommand) .then(amountArgument.executes { executeSkillUpCommand(it, IntegerArgumentType.getInteger(it, "amount")) }) ) ) ) - ).then(CommandManager.literal("refund") - .then(CommandManager.literal("get").then(playerArgument.executes(::executeRefundGetCommand))) + ).then(Commands.literal("refund") + .then(Commands.literal("get").then(playerArgument.executes(::executeRefundGetCommand))) .then( - CommandManager.literal("add").then( + Commands.literal("add").then( playerArgument.executes(::executeRefundAddCommand).then( amountArgument.executes { executeRefundAddCommand(it, IntegerArgumentType.getInteger(it, "amount")) } ) ) ) .then( - CommandManager.literal("skill").then( + Commands.literal("skill").then( identifierArgument.suggests(MODIFIABLE_ATTRIBUTES_SUGGESTIONS) .then(playerArgument.then( amountArgument.executes { executeRefundAttributeCommand(it, IntegerArgumentType.getInteger(it, "amount")) } @@ -96,45 +96,45 @@ object PlayerEXCommands { ) } - private fun isOp(source: ServerCommandSource) = source.hasPermissionLevel(2) + private fun isOp(source: CommandSourceStack) = source.hasPermission(2) private fun executeLevelGetCommand(ctx: Context): Int { - val player = EntityArgumentType.getPlayer(ctx, "player") + val player = EntityArgument.getPlayer(ctx, "player") return DataAttributesAPI.getValue(PlayerEXAttributes.LEVEL, player).map { - ctx.source.sendFeedback({ Text.translatable("playerex.command.level_get", player.name, it.toInt()).append(Text.of("/${PlayerEXAttributes.LEVEL.maxValue.toInt()}")) }, false) + ctx.source.sendSuccess({ Component.translatable("playerex.command.level_get", player.name, it.toInt()).append(Component.nullToEmpty("/${PlayerEXAttributes.LEVEL.maxValue.toInt()}")) }, false) 1 }.orElse(-1) } private fun executeSkillGetCommand(ctx: Context): Int { - val player = EntityArgumentType.getPlayer(ctx, "player") + val player = EntityArgument.getPlayer(ctx, "player") val component = PlayerEXComponents.PLAYER_DATA.get(player) - val supplier = EntityAttributeSupplier(IdentifierArgumentType.getIdentifier(ctx, "id")) + val supplier = EntityAttributeSupplier(ResourceLocationArgument.getId(ctx, "id")) return DataAttributesAPI.getValue(supplier, player).map { value -> - ctx.source.sendFeedback({ Text.translatable("playerex.command.skill_get", Text.translatable(supplier.get().get().translationKey), value.toInt(), player.name) }, false) + ctx.source.sendSuccess({ Component.translatable("playerex.command.skill_get", Component.translatable(supplier.get().get().descriptionId), value.toInt(), player.name) }, false) 1 }.orElse(-1) } private fun executeRefundGetCommand(ctx: Context): Int { - val player = EntityArgumentType.getPlayer(ctx, "player") - ctx.source.sendFeedback({ Text.translatable("playerex.command.refund.get", player.name, player.data.refundablePoints) }, false) + val player = EntityArgument.getPlayer(ctx, "player") + ctx.source.sendSuccess({ Component.translatable("playerex.command.refund.get", player.name, player.data.refundablePoints) }, false) return 1 } private fun executeRefundAttributeCommand(ctx: Context, amount: Int = 1): Int { - val player = EntityArgumentType.getPlayer(ctx, "player") + val player = EntityArgument.getPlayer(ctx, "player") - val supplier = EntityAttributeSupplier(IdentifierArgumentType.getIdentifier(ctx, "id")) + val supplier = EntityAttributeSupplier(ResourceLocationArgument.getId(ctx, "id")) return DataAttributesAPI.getValue(supplier, player).map { val attribute = supplier.get().get() - val computed = MathHelper.clamp(amount, 0, it.toInt()) + val computed = Mth.clamp(amount, 0, it.toInt()) if (player.data.refund(attribute, computed)) { - ctx.source.sendFeedback({ Text.translatable("playerex.command.refunded", amount, Text.translatable(attribute.translationKey), player.name) }, false) - ctx.source.sendFeedback(updatedValueText(attribute, it - amount), false) + ctx.source.sendSuccess({ Component.translatable("playerex.command.refunded", amount, Component.translatable(attribute.descriptionId), player.name) }, false) + ctx.source.sendSuccess(updatedValueText(attribute, it - amount), false) 1 } else { @@ -144,62 +144,62 @@ object PlayerEXCommands { } private fun executeRefundAddCommand(ctx: Context, amount: Int = 1): Int { - val player = EntityArgumentType.getPlayer(ctx, "player") + val player = EntityArgument.getPlayer(ctx, "player") player.data.addRefundablePoints(amount) - ctx.source.sendFeedback({ Text.translatable("playerex.command.refund.add", amount, player.name) }, false) + ctx.source.sendSuccess({ Component.translatable("playerex.command.refund.add", amount, player.name) }, false) return 1 } private fun executeSkillUpCommand(ctx: Context, amount: Int = 1): Int { - val player = EntityArgumentType.getPlayer(ctx, "player") - val supplier = EntityAttributeSupplier(IdentifierArgumentType.getIdentifier(ctx, "id")) + val player = EntityArgument.getPlayer(ctx, "player") + val supplier = EntityAttributeSupplier(ResourceLocationArgument.getId(ctx, "id")) return DataAttributesAPI.getValue(supplier, player).map { val attribute = supplier.get().get() - val computed = MathHelper.clamp(amount, 0, (attribute as IEntityAttribute).`data_attributes$max`().toInt() - it.toInt()) + val computed = Mth.clamp(amount, 0, (attribute as IEntityAttribute).`data_attributes$max`().toInt() - it.toInt()) if (player.data.skillUp(attribute, computed, true)) { - ctx.source.sendFeedback({ Text.translatable("playerex.command.skill_up", computed, Text.translatable(attribute.translationKey), player.name) }, false) - ctx.source.sendFeedback(updatedValueText(attribute, it + computed), false) + ctx.source.sendSuccess({ Component.translatable("playerex.command.skill_up", computed, Component.translatable(attribute.descriptionId), player.name) }, false) + ctx.source.sendSuccess(updatedValueText(attribute, it + computed), false) 1 } else { - ctx.source.sendFeedback(maxErrorMessage(player, attribute), false) + ctx.source.sendSuccess(maxErrorMessage(player, attribute), false) -1 } }.orElse(-1) } private fun executeLevelUpCommand(ctx: Context, amount: Int = 1): Int { - val player = EntityArgumentType.getPlayer(ctx, "player") + val player = EntityArgument.getPlayer(ctx, "player") return DataAttributesAPI.getValue(PlayerEXAttributes.LEVEL, player).map { value -> val attribute = PlayerEXAttributes.LEVEL - val computed = MathHelper.clamp(amount, 0, (attribute as IEntityAttribute).`data_attributes$max`().toInt() - value.toInt()) + val computed = Mth.clamp(amount, 0, (attribute as IEntityAttribute).`data_attributes$max`().toInt() - value.toInt()) if (!player.data.levelUp(computed, true)) { // todo: err message, for now just -1 return@map -1 } - ctx.source.sendFeedback({ Text.translatable("playerex.command.level_up", computed, player.name) }, false) - ctx.source.sendFeedback(updatedValueText(attribute, value + computed), false) + ctx.source.sendSuccess({ Component.translatable("playerex.command.level_up", computed, player.name) }, false) + ctx.source.sendSuccess(updatedValueText(attribute, value + computed), false) return@map 1 }.orElse(-1) } private fun executeResetCommand(ctx: Context, retained: Int = 0): Int { - val player = EntityArgumentType.getPlayer(ctx, "player") + val player = EntityArgument.getPlayer(ctx, "player") PlayerEXComponents.PLAYER_DATA.get(player).reset(retained) - ctx.source.sendFeedback( + ctx.source.sendSuccess( { - Text.translatable("playerex.command.reset", player.name).also { if (retained > 0) it.append(" [${retained}%]") } + Component.translatable("playerex.command.reset", player.name).also { if (retained > 0) it.append(" [${retained}%]") } }, false ) @@ -210,9 +210,9 @@ object PlayerEXCommands { private fun executeResetAllCommand(ctx: Context, retained: Int = 0): Int { PlayerLookup.all(ctx.source.server).forEach { PlayerEXComponents.PLAYER_DATA.get(it).reset(retained) } - ctx.source.sendFeedback( + ctx.source.sendSuccess( { - Text.translatable("playerex.command.reset", "(*)") + Component.translatable("playerex.command.reset", "(*)") .also { if (retained > 0) it.append(", ${retained}%") } }, false @@ -221,11 +221,11 @@ object PlayerEXCommands { return 1 } - private fun maxErrorMessage(player: PlayerEntity, attribute: EntityAttribute): () -> MutableText = { - Text.translatable("playerex.command.max_error", Text.translatable(attribute.translationKey), player.name) + private fun maxErrorMessage(player: Player, attribute: Attribute): () -> MutableComponent = { + Component.translatable("playerex.command.max_error", Component.translatable(attribute.descriptionId), player.name) } - private fun updatedValueText(attribute: EntityAttribute, value: Double): () -> MutableText = { - Text.translatable("playerex.command.updated_result", value.toInt()).append(Text.of("/${(attribute as IEntityAttribute).`data_attributes$max`().toInt()}")) + private fun updatedValueText(attribute: Attribute, value: Double): () -> MutableComponent = { + Component.translatable("playerex.command.updated_result", value.toInt()).append(Component.nullToEmpty("/${(attribute as IEntityAttribute).`data_attributes$max`().toInt()}")) } } \ No newline at end of file diff --git a/src/main/kotlin/com/bibireden/playerex/api/attribute/DefaultAttributeImpl.kt b/src/main/kotlin/com/bibireden/playerex/api/attribute/DefaultAttributeImpl.kt index f6124e97..032df745 100644 --- a/src/main/kotlin/com/bibireden/playerex/api/attribute/DefaultAttributeImpl.kt +++ b/src/main/kotlin/com/bibireden/playerex/api/attribute/DefaultAttributeImpl.kt @@ -9,16 +9,16 @@ import com.bibireden.playerex.compat.CompatUtils import com.bibireden.playerex.ext.id import de.dafuqs.additionalentityattributes.AdditionalEntityAttributes import net.fabric_extras.ranged_weapon.api.EntityAttributes_RangedWeapon -import net.minecraft.entity.attribute.EntityAttributes -import net.minecraft.util.Identifier +import net.minecraft.resources.ResourceLocation +import net.minecraft.world.entity.ai.attributes.Attributes object DefaultAttributeImpl { - val OVERRIDES: Map = mutableMapOf( + val OVERRIDES: Map = mutableMapOf( PlayerEXAttributes.POISON_RESISTANCE.id to AttributeOverride( smoothness = 1.0, formula = StackingFormula.Diminished ), - EntityAttributes.GENERIC_KNOCKBACK_RESISTANCE.id to AttributeOverride( + Attributes.KNOCKBACK_RESISTANCE.id to AttributeOverride( smoothness = 1.0, formula = StackingFormula.Diminished ), @@ -62,7 +62,7 @@ object DefaultAttributeImpl { smoothness = 1.0, formula = StackingFormula.Diminished ), - EntityAttributes.GENERIC_LUCK.id to AttributeOverride( + Attributes.LUCK.id to AttributeOverride( smoothness = 1.0, formula = StackingFormula.Diminished ), @@ -83,22 +83,22 @@ object DefaultAttributeImpl { } } - val FUNCTIONS: Map> = mapOf( + val FUNCTIONS: Map> = mapOf( PlayerEXAttributes.CONSTITUTION.id to listOf( - AttributeFunction(EntityAttributes.GENERIC_MAX_HEALTH.id, StackingBehavior.Add, 0.5), - AttributeFunction(EntityAttributes.GENERIC_ARMOR.id, StackingBehavior.Add, 0.25), + AttributeFunction(Attributes.MAX_HEALTH.id, StackingBehavior.Add, 0.5), + AttributeFunction(Attributes.ARMOR.id, StackingBehavior.Add, 0.25), AttributeFunction(AdditionalEntityAttributes.MAGIC_PROTECTION.id, StackingBehavior.Add, 0.25), AttributeFunction(AdditionalEntityAttributes.LUNG_CAPACITY.id, StackingBehavior.Add, 0.01), AttributeFunction(PlayerEXAttributes.POISON_RESISTANCE.id, StackingBehavior.Add, 0.01), ), PlayerEXAttributes.STRENGTH.id to listOf( - AttributeFunction(EntityAttributes.GENERIC_ATTACK_DAMAGE.id, StackingBehavior.Multiply, 0.02), - AttributeFunction(EntityAttributes.GENERIC_KNOCKBACK_RESISTANCE.id, StackingBehavior.Add, 0.01), + AttributeFunction(Attributes.ATTACK_DAMAGE.id, StackingBehavior.Multiply, 0.02), + AttributeFunction(Attributes.KNOCKBACK_RESISTANCE.id, StackingBehavior.Add, 0.01), AttributeFunction(PlayerEXAttributes.MELEE_CRITICAL_DAMAGE.id, StackingBehavior.Add, 0.005), AttributeFunction(PlayerEXAttributes.BREAKING_SPEED.id, StackingBehavior.Add, 0.01), ), PlayerEXAttributes.DEXTERITY.id to listOf( - AttributeFunction(EntityAttributes.GENERIC_ATTACK_SPEED.id, StackingBehavior.Multiply, 0.01), + AttributeFunction(Attributes.ATTACK_SPEED.id, StackingBehavior.Multiply, 0.01), AttributeFunction(PlayerEXAttributes.RANGED_CRITICAL_DAMAGE.id, StackingBehavior.Add, 0.005), AttributeFunction(EntityAttributes_RangedWeapon.HASTE.id, StackingBehavior.Multiply, 0.02), AttributeFunction(EntityAttributes_RangedWeapon.DAMAGE.id, StackingBehavior.Multiply, 0.02), @@ -123,7 +123,7 @@ object DefaultAttributeImpl { AttributeFunction(PlayerEXAttributes.MELEE_CRITICAL_CHANCE.id, StackingBehavior.Add, 0.02), AttributeFunction(PlayerEXAttributes.RANGED_CRITICAL_CHANCE.id, StackingBehavior.Add, 0.02), // loot table chance?? wh- - AttributeFunction(EntityAttributes.GENERIC_LUCK.id, StackingBehavior.Add, 0.05), + AttributeFunction(Attributes.LUCK.id, StackingBehavior.Add, 0.05), AttributeFunction(PlayerEXAttributes.EVASION.id, StackingBehavior.Add, 0.01), ).apply { if (CompatUtils.isModLoaded("spell_power")) { @@ -131,8 +131,8 @@ object DefaultAttributeImpl { } }, ) - val ENTITY_TYPES: Map = mapOf( - Identifier.of("minecraft", "player")!! to EntityTypeData(mapOf( + val ENTITY_TYPES: Map = mapOf( + ResourceLocation.tryBuild("minecraft", "player")!! to EntityTypeData(mapOf( PlayerEXAttributes.LEVEL.id to 0.0, PlayerEXAttributes.CONSTITUTION.id to 0.0, PlayerEXAttributes.STRENGTH.id to 0.0, diff --git a/src/main/kotlin/com/bibireden/playerex/api/attribute/ModdedAttributes.kt b/src/main/kotlin/com/bibireden/playerex/api/attribute/ModdedAttributes.kt index a1553991..c7770007 100644 --- a/src/main/kotlin/com/bibireden/playerex/api/attribute/ModdedAttributes.kt +++ b/src/main/kotlin/com/bibireden/playerex/api/attribute/ModdedAttributes.kt @@ -1,7 +1,7 @@ package com.bibireden.playerex.api.attribute import com.bibireden.data_attributes.api.attribute.EntityAttributeSupplier -import net.minecraft.util.Identifier +import net.minecraft.resources.ResourceLocation /** * Attributes that specifically do not relate to **PlayerEX**, but are used by the mod. @@ -10,8 +10,8 @@ import net.minecraft.util.Identifier */ object ModdedAttributes { @JvmField - val SPELL_HASTE = EntityAttributeSupplier(Identifier.of("spell_power", "haste")!!) + val SPELL_HASTE = EntityAttributeSupplier(ResourceLocation.tryBuild("spell_power", "haste")!!) @JvmField - val SPELL_CRITICAL_CHANCE = EntityAttributeSupplier(Identifier.of("spell_power", "critical_chance")!!) + val SPELL_CRITICAL_CHANCE = EntityAttributeSupplier(ResourceLocation.tryBuild("spell_power", "critical_chance")!!) } \ No newline at end of file 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 222acd2c..16bb9c54 100644 --- a/src/main/kotlin/com/bibireden/playerex/api/attribute/PlayerEXAttributes.kt +++ b/src/main/kotlin/com/bibireden/playerex/api/attribute/PlayerEXAttributes.kt @@ -2,10 +2,10 @@ package com.bibireden.playerex.api.attribute import com.bibireden.playerex.PlayerEX import com.bibireden.playerex.ext.id -import net.minecraft.entity.attribute.ClampedEntityAttribute -import net.minecraft.registry.Registries -import net.minecraft.registry.Registry -import net.minecraft.util.Identifier +import net.minecraft.core.Registry +import net.minecraft.core.registries.BuiltInRegistries +import net.minecraft.resources.ResourceLocation +import net.minecraft.world.entity.ai.attributes.RangedAttribute object PlayerEXAttributes { @JvmField @@ -71,12 +71,12 @@ object PlayerEXAttributes { @JvmField val RANGED_CRITICAL_DAMAGE = register("ranged_crit_damage", 0.0, 0.0, 1000000.0) - fun register(path: String, base: Double, min: Double, max: Double): ClampedEntityAttribute { - val attribute = ClampedEntityAttribute("attribute.name.${PlayerEX.MOD_ID}.$path", base, min, max) - return Registry.register(Registries.ATTRIBUTE, Identifier.of(PlayerEX.MOD_ID, path)!!, attribute) + fun register(path: String, base: Double, min: Double, max: Double): RangedAttribute { + val attribute = RangedAttribute("attribute.name.${PlayerEX.MOD_ID}.$path", base, min, max) + return Registry.register(BuiltInRegistries.ATTRIBUTE, ResourceLocation.tryBuild(PlayerEX.MOD_ID, path)!!, attribute) } - val PRIMARY_ATTRIBUTE_IDS: Set = setOf( + val PRIMARY_ATTRIBUTE_IDS: Set = setOf( CONSTITUTION.id, STRENGTH.id, DEXTERITY.id, diff --git a/src/main/kotlin/com/bibireden/playerex/api/attribute/TradeSkillAttributes.kt b/src/main/kotlin/com/bibireden/playerex/api/attribute/TradeSkillAttributes.kt index 9109accc..950f0137 100644 --- a/src/main/kotlin/com/bibireden/playerex/api/attribute/TradeSkillAttributes.kt +++ b/src/main/kotlin/com/bibireden/playerex/api/attribute/TradeSkillAttributes.kt @@ -2,7 +2,7 @@ package com.bibireden.playerex.api.attribute import com.bibireden.playerex.api.attribute.PlayerEXAttributes.register import com.bibireden.playerex.ext.id -import net.minecraft.util.Identifier +import net.minecraft.resources.ResourceLocation object TradeSkillAttributes { @JvmField @@ -27,7 +27,7 @@ object TradeSkillAttributes { val FARMING = register("farming", 0.0, 0.0, 100.0); @JvmField - val IDS: Set = setOf( + val IDS: Set = setOf( MINING.id, ALCHEMY.id, FISHING.id, diff --git a/src/main/kotlin/com/bibireden/playerex/api/damage/DamageFunction.kt b/src/main/kotlin/com/bibireden/playerex/api/damage/DamageFunction.kt index 9bc43407..29ca6388 100644 --- a/src/main/kotlin/com/bibireden/playerex/api/damage/DamageFunction.kt +++ b/src/main/kotlin/com/bibireden/playerex/api/damage/DamageFunction.kt @@ -1,7 +1,7 @@ package com.bibireden.playerex.api.damage -import net.minecraft.entity.LivingEntity -import net.minecraft.entity.damage.DamageSource +import net.minecraft.world.damagesource.DamageSource +import net.minecraft.world.entity.LivingEntity fun interface DamageFunction { /** diff --git a/src/main/kotlin/com/bibireden/playerex/api/damage/DamagePredicate.kt b/src/main/kotlin/com/bibireden/playerex/api/damage/DamagePredicate.kt index 9ef13df6..4ed24764 100644 --- a/src/main/kotlin/com/bibireden/playerex/api/damage/DamagePredicate.kt +++ b/src/main/kotlin/com/bibireden/playerex/api/damage/DamagePredicate.kt @@ -1,7 +1,7 @@ package com.bibireden.playerex.api.damage -import net.minecraft.entity.LivingEntity -import net.minecraft.entity.damage.DamageSource +import net.minecraft.world.damagesource.DamageSource +import net.minecraft.world.entity.LivingEntity fun interface DamagePredicate { /** diff --git a/src/main/kotlin/com/bibireden/playerex/api/event/LivingEntityEvents.kt b/src/main/kotlin/com/bibireden/playerex/api/event/LivingEntityEvents.kt index 63192a66..c8b0041d 100644 --- a/src/main/kotlin/com/bibireden/playerex/api/event/LivingEntityEvents.kt +++ b/src/main/kotlin/com/bibireden/playerex/api/event/LivingEntityEvents.kt @@ -2,8 +2,8 @@ package com.bibireden.playerex.api.event import net.fabricmc.fabric.api.event.Event import net.fabricmc.fabric.api.event.EventFactory -import net.minecraft.entity.LivingEntity -import net.minecraft.entity.damage.DamageSource +import net.minecraft.world.damagesource.DamageSource +import net.minecraft.world.entity.LivingEntity object LivingEntityEvents { /** diff --git a/src/main/kotlin/com/bibireden/playerex/api/event/PlayerEXSoundEvents.kt b/src/main/kotlin/com/bibireden/playerex/api/event/PlayerEXSoundEvents.kt index bb2e02a8..9338fecf 100644 --- a/src/main/kotlin/com/bibireden/playerex/api/event/PlayerEXSoundEvents.kt +++ b/src/main/kotlin/com/bibireden/playerex/api/event/PlayerEXSoundEvents.kt @@ -1,10 +1,10 @@ package com.bibireden.playerex.api.event import com.bibireden.playerex.PlayerEX -import net.minecraft.sound.SoundEvent +import net.minecraft.sounds.SoundEvent object PlayerEXSoundEvents { - val LEVEL_UP_SOUND = SoundEvent.of(PlayerEX.id("level_up")) - val SPEND_SOUND = SoundEvent.of(PlayerEX.id("spend")) - val REFUND_SOUND = SoundEvent.of(PlayerEX.id("refund")) + val LEVEL_UP_SOUND = SoundEvent.createVariableRangeEvent(PlayerEX.id("level_up")) + val SPEND_SOUND = SoundEvent.createVariableRangeEvent(PlayerEX.id("spend")) + val REFUND_SOUND = SoundEvent.createVariableRangeEvent(PlayerEX.id("refund")) } \ No newline at end of file diff --git a/src/main/kotlin/com/bibireden/playerex/api/event/PlayerEntityEvents.kt b/src/main/kotlin/com/bibireden/playerex/api/event/PlayerEntityEvents.kt index 54168851..068bde7b 100644 --- a/src/main/kotlin/com/bibireden/playerex/api/event/PlayerEntityEvents.kt +++ b/src/main/kotlin/com/bibireden/playerex/api/event/PlayerEntityEvents.kt @@ -4,8 +4,8 @@ import com.bibireden.playerex.api.event.PlayerEntityEvents.ShouldCritical import com.bibireden.playerex.api.event.PlayerEntityEvents.AttackCriticalDamage import net.fabricmc.fabric.api.event.Event import net.fabricmc.fabric.api.event.EventFactory -import net.minecraft.entity.Entity -import net.minecraft.entity.player.PlayerEntity +import net.minecraft.world.entity.Entity +import net.minecraft.world.entity.player.Player object PlayerEntityEvents { @@ -14,7 +14,7 @@ object PlayerEntityEvents { */ @JvmField val ON_CRITICAL: Event = EventFactory.createArrayBacked(AttackCriticalDamage::class.java) { callbacks: Array -> - AttackCriticalDamage { player: PlayerEntity, target: Entity, amount: Float -> + AttackCriticalDamage { player: Player, target: Entity, amount: Float -> var previous = amount for (callback in callbacks) { previous = callback.onCriticalDamage(player, target, previous) @@ -28,7 +28,7 @@ object PlayerEntityEvents { */ @JvmField val SHOULD_CRITICAL: Event = EventFactory.createArrayBacked(ShouldCritical::class.java) { callbacks: Array -> - ShouldCritical { player: PlayerEntity, target: Entity, vanilla: Boolean -> + ShouldCritical { player: Player, target: Entity, vanilla: Boolean -> for (callback in callbacks) { if (callback.shouldCritical(player, target, vanilla)) return@ShouldCritical true } @@ -37,10 +37,10 @@ object PlayerEntityEvents { } fun interface AttackCriticalDamage { - fun onCriticalDamage(player: PlayerEntity, target: Entity, amount: Float): Float + fun onCriticalDamage(player: Player, target: Entity, amount: Float): Float } fun interface ShouldCritical { - fun shouldCritical(player: PlayerEntity, target: Entity, vanilla: Boolean): Boolean + fun shouldCritical(player: Player, target: Entity, vanilla: Boolean): Boolean } } \ No newline at end of file diff --git a/src/main/kotlin/com/bibireden/playerex/components/experience/ExperienceDataComponent.kt b/src/main/kotlin/com/bibireden/playerex/components/experience/ExperienceDataComponent.kt index 95c90ed5..bd428c9a 100644 --- a/src/main/kotlin/com/bibireden/playerex/components/experience/ExperienceDataComponent.kt +++ b/src/main/kotlin/com/bibireden/playerex/components/experience/ExperienceDataComponent.kt @@ -1,14 +1,14 @@ package com.bibireden.playerex.components.experience import com.bibireden.playerex.PlayerEX -import net.minecraft.nbt.NbtCompound -import net.minecraft.world.chunk.Chunk +import net.minecraft.nbt.CompoundTag +import net.minecraft.world.level.chunk.ChunkAccess import kotlin.math.max import kotlin.math.min import kotlin.random.Random class ExperienceDataComponent( - val chunk: Chunk, + val chunk: ChunkAccess, private var _ticks: Int = 0, private var _restorativeForceTicks: Int = PlayerEX.CONFIG.restorativeForceTicks, private var _restorativeForceMultiplier: Int = PlayerEX.CONFIG.restorativeForceMultiplier, @@ -20,17 +20,17 @@ class ExperienceDataComponent( val dynamicMultiplier = this._expNegationMultiplier + ((1.0F - this._expNegationMultiplier) * (1.0F - (0.1F * amount))) this._expNegationFactor = max(this._expNegationFactor * dynamicMultiplier, 0.0F) - this.chunk.setNeedsSaving(true) - return false; + this.chunk.isUnsaved = true + return false } override fun resetExperienceNegationFactor() { this._expNegationMultiplier = 1 } - override fun readFromNbt(tag: NbtCompound) { + override fun readFromNbt(tag: CompoundTag) { this._expNegationFactor = tag.getFloat("exp_factor") } - override fun writeToNbt(tag: NbtCompound) { + override fun writeToNbt(tag: CompoundTag) { tag.putFloat("exp_factor", this._expNegationFactor) } @@ -40,7 +40,7 @@ class ExperienceDataComponent( else { this._ticks = 0 this._expNegationFactor = min(this._expNegationFactor * this._restorativeForceMultiplier, 1.0F) - this.chunk.setNeedsSaving(true) + this.chunk.isUnsaved = true } } } \ No newline at end of file diff --git a/src/main/kotlin/com/bibireden/playerex/components/player/IPlayerDataComponent.kt b/src/main/kotlin/com/bibireden/playerex/components/player/IPlayerDataComponent.kt index 39f68403..3a128727 100644 --- a/src/main/kotlin/com/bibireden/playerex/components/player/IPlayerDataComponent.kt +++ b/src/main/kotlin/com/bibireden/playerex/components/player/IPlayerDataComponent.kt @@ -1,7 +1,7 @@ package com.bibireden.playerex.components.player import dev.onyxstudios.cca.api.v3.component.Component -import net.minecraft.entity.attribute.EntityAttribute +import net.minecraft.world.entity.ai.attributes.Attribute /** Utilized to access and modify PlayerEX attribute modifiers. */ interface IPlayerDataComponent : Component { @@ -10,16 +10,16 @@ interface IPlayerDataComponent : Component { /** Returns the current number of refundable points. */ val refundablePoints: Int - /** Gets the cached [EntityAttribute] modifier value, or provides `0` if it does not exist. */ - fun get(attribute: EntityAttribute): Double - /** Applies the provided modifier value to the [EntityAttribute], and creates it if it does not exist. */ - fun set(attribute: EntityAttribute, value: Int) - /** Removes the [EntityAttribute] modifier if it exists. */ - fun remove(attribute: EntityAttribute) - /** Adds the current [EntityAttribute]'s value with the provided value together. */ - fun add(attribute: EntityAttribute, value: Double) + /** Gets the cached [Attribute] modifier value, or provides `0` if it does not exist. */ + fun get(attribute: Attribute): Double + /** Applies the provided modifier value to the [Attribute], and creates it if it does not exist. */ + fun set(attribute: Attribute, value: Int) + /** Removes the [Attribute] modifier if it exists. */ + fun remove(attribute: Attribute) + /** Adds the current [Attribute]'s value with the provided value together. */ + fun add(attribute: Attribute, value: Double) /** - * Resets all the data (which includes all [EntityAttribute] modifiers) to their defaults. + * Resets all the data (which includes all [Attribute] modifiers) to their defaults. * * @param percent Depending on what is provided, it will preserve the amount of skill points. */ @@ -40,8 +40,8 @@ interface IPlayerDataComponent : Component { * * If not possible, it will return `false`. * This can be changed by setting `true` to the [override] argument. */ - fun skillUp(skill: EntityAttribute, amount: Int, override: Boolean = false): Boolean + fun skillUp(skill: Attribute, amount: Int, override: Boolean = false): Boolean /** Refunds skill points based on the amount provided and how much [refundablePoints] the player currently has. */ - fun refund(skill: EntityAttribute, amount: Int): Boolean + fun refund(skill: Attribute, amount: Int): Boolean } \ No newline at end of file diff --git a/src/main/kotlin/com/bibireden/playerex/components/player/PlayerDataComponent.kt b/src/main/kotlin/com/bibireden/playerex/components/player/PlayerDataComponent.kt index e3df3708..62c02de9 100644 --- a/src/main/kotlin/com/bibireden/playerex/components/player/PlayerDataComponent.kt +++ b/src/main/kotlin/com/bibireden/playerex/components/player/PlayerDataComponent.kt @@ -21,32 +21,32 @@ import dev.onyxstudios.cca.api.v3.component.sync.AutoSyncedComponent import dev.onyxstudios.cca.api.v3.component.sync.ComponentPacketWriter import io.wispforest.endec.Endec import io.wispforest.endec.impl.StructEndecBuilder -import net.minecraft.entity.attribute.EntityAttribute -import net.minecraft.entity.attribute.EntityAttributeInstance -import net.minecraft.entity.attribute.EntityAttributeModifier -import net.minecraft.entity.player.PlayerEntity -import net.minecraft.nbt.NbtCompound -import net.minecraft.network.PacketByteBuf -import net.minecraft.registry.Registries -import net.minecraft.server.network.ServerPlayerEntity -import net.minecraft.util.Identifier -import net.minecraft.util.math.MathHelper +import net.minecraft.core.registries.BuiltInRegistries +import net.minecraft.nbt.CompoundTag +import net.minecraft.network.FriendlyByteBuf +import net.minecraft.resources.ResourceLocation +import net.minecraft.server.level.ServerPlayer +import net.minecraft.util.Mth +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.player.Player import kotlin.math.round /** - * Implementation of player-data that is meant to be synchronized. Contains [EntityAttribute] data and provided modifiers, + * Implementation of player-data that is meant to be synchronized. Contains [Attribute] data and provided modifiers, * skill points and refundable points. */ class PlayerDataComponent( - private val player: PlayerEntity, + private val player: Player, private var _refundablePoints: Int = 0, private var _skillPoints: Int = 0, - private var _modifiers: MutableMap = mutableMapOf(), + private var _modifiers: MutableMap = mutableMapOf(), var isLevelUpNotified: Boolean = false, ) : IPlayerDataComponent, AutoSyncedComponent { - data class Packet(val modifiers: Map, val refundablePoints: Int, val skillPoints: Int, val isLevelUpNotified: Boolean) + data class Packet(val modifiers: Map, val refundablePoints: Int, val skillPoints: Int, val isLevelUpNotified: Boolean) - private fun toPacketNbt(): NbtCompound = NbtCompound().also(::writeToNbt) + private fun toPacketNbt(): CompoundTag = CompoundTag().also(::writeToNbt) companion object { val ENDEC = StructEndecBuilder.of( @@ -59,32 +59,32 @@ class PlayerDataComponent( } /** - * Attempts to fetch an [EntityAttributeInstance] based on the provided [Identifier]. + * Attempts to fetch an [AttributeInstance] based on the provided [ResourceLocation]. * * @return a [Pair] of the instance, and whether that instance contains an existing modifier that has the UUID [PlayerEXModifiers.UUID]. */ - private fun getInstance(key: Identifier): Pair? { - val attribute = Registries.ATTRIBUTE[key] ?: return null - val instance = this.player.attributes.getCustomInstance(attribute) ?: return null + private fun getInstance(key: ResourceLocation): Pair? { + val attribute = BuiltInRegistries.ATTRIBUTE[key] ?: return null + val instance = this.player.attributes.getInstance(attribute) ?: return null return Pair(instance, instance.getModifier(PlayerEXModifiers.UUID) != null) } private fun sync(packet: ComponentPacketWriter) { - this.player.world.takeUnless { it.isClient }?.let { world -> + this.player.level().takeUnless { it.isClientSide() }?.let { world -> PlayerEXComponents.PLAYER_DATA.sync(this.player, packet) } } /** - * Attempts to set a special PlayerEX-specific modifier to an [EntityAttributeInstance] based on the [Identifier] key provided. + * Attempts to set a special PlayerEX-specific modifier to an [AttributeInstance] based on the [ResourceLocation] key provided. */ - private fun trySet(key: Identifier, value: Double): Boolean { + private fun trySet(key: ResourceLocation, value: Double): Boolean { val (instance, isPlayerEXModifierPresent) = this.getInstance(key) ?: return false if (isPlayerEXModifierPresent) { (instance as IEntityAttributeInstance).updateModifier(PlayerEXModifiers.UUID, value) } else { - instance.addPersistentModifier(EntityAttributeModifier(PlayerEXModifiers.UUID, "PlayerEX Attribute", value, EntityAttributeModifier.Operation.ADDITION)) + instance.addPermanentModifier(AttributeModifier(PlayerEXModifiers.UUID, "PlayerEX Attribute", value, AttributeModifier.Operation.ADDITION)) } this._modifiers[key] = value return true @@ -92,11 +92,11 @@ class PlayerDataComponent( // todo: this function angers me!!!! 😡 remove should be suitable enough instead of a try. /** - * Attempts to remove a special PlayerEX modifier if present on the [EntityAttributeInstance] linked by the provided [Identifier] key. + * Attempts to remove a special PlayerEX modifier if present on the [AttributeInstance] linked by the provided [ResourceLocation] key. * - * @return [Boolean] Whether there was an existing [EntityAttributeInstance], whether an [EntityAttributeModifier] was removed or not. + * @return [Boolean] Whether there was an existing [AttributeInstance], whether an [AttributeInstance] was removed or not. * */ - private fun tryRemove(key: Identifier): Boolean { + private fun tryRemove(key: ResourceLocation): Boolean { return this.getInstance(key)?.let { (instance, isModifierPresent) -> if (isModifierPresent) { instance.removeModifier(PlayerEXModifiers.UUID) @@ -104,24 +104,24 @@ class PlayerDataComponent( } != null } - override fun get(attribute: EntityAttribute): Double { + override fun get(attribute: Attribute): Double { return this._modifiers.getOrDefault(attribute.id, 0.0) } - override fun set(attribute: EntityAttribute, value: Int) { + override fun set(attribute: Attribute, value: Int) { val identifier = attribute.id - val attributeValue = attribute.clamp(value.toDouble()) + val attributeValue = attribute.sanitizeValue(value.toDouble()) if (!this.trySet(identifier, attributeValue)) return this.sync { buf, player -> buf.writeNbt(toPacketNbt())} } - override fun add(attribute: EntityAttribute, value: Double) { + override fun add(attribute: Attribute, value: Double) { this.set(attribute, (value + this.get(attribute)).toInt()) } - override fun remove(attribute: EntityAttribute) { + override fun remove(attribute: Attribute) { val identifier = attribute.id if (!this.tryRemove(identifier).also { if (it) this._modifiers.remove(identifier) }) return this.sync { buf, player -> buf.writeNbt(toPacketNbt())} @@ -130,7 +130,7 @@ class PlayerDataComponent( override fun reset(percent: Int) { val partition = if (percent == 0) 0.0 else percent / 100.0 - val kept = mutableMapOf() + val kept = mutableMapOf() for ((id, value) in this.modifiers) { if (partition == 0.0) { this.tryRemove(id) @@ -163,7 +163,7 @@ class PlayerDataComponent( maxRefundPoints += condition(this, this.player) } - this._refundablePoints = round(MathHelper.clamp((this.refundablePoints + points).toDouble(), 0.0, maxRefundPoints)).toInt() + this._refundablePoints = round(Mth.clamp((this.refundablePoints + points).toDouble(), 0.0, maxRefundPoints)).toInt() this.sync { buf, _ -> buf.writeNbt(toPacketNbt())} @@ -185,7 +185,7 @@ class PlayerDataComponent( val skillPoints = CONFIG.skillPointsPerLevelUp * amount val component = PlayerEXComponents.PLAYER_DATA.get(player) - if (!override) player.addExperienceLevels(-required) + if (!override) player.giveExperienceLevels(-required) component.addSkillPoints(skillPoints) component.set(PlayerEXAttributes.LEVEL, expectedLevel.toInt()) @@ -195,7 +195,7 @@ class PlayerDataComponent( }.orElse(false) } - override fun skillUp(skill: EntityAttribute, amount: Int, override: Boolean): Boolean { + override fun skillUp(skill: Attribute, amount: Int, override: Boolean): Boolean { if (amount <= 0) return false return DataAttributesAPI.getValue(skill, player).map { current -> @@ -214,7 +214,7 @@ class PlayerDataComponent( }.orElse(false) } - override fun refund(skill: EntityAttribute, amount: Int): Boolean { + override fun refund(skill: Attribute, amount: Int): Boolean { if (amount <= 0 || this.refundablePoints < amount) return false return DataAttributesAPI.getValue(skill, player).map { value -> if (amount > value) return@map false @@ -229,7 +229,7 @@ class PlayerDataComponent( }.orElse(false) } - val modifiers: Map + val modifiers: Map get() = this._modifiers override val skillPoints: Int @@ -238,7 +238,7 @@ class PlayerDataComponent( override val refundablePoints: Int get() = this._refundablePoints - override fun readFromNbt(tag: NbtCompound) { + override fun readFromNbt(tag: CompoundTag) { ENDEC.decodeFully(NbtDeserializer::of, tag.get("DART")).also { this._modifiers = it.modifiers.toMutableMap() this._refundablePoints = it.refundablePoints @@ -247,13 +247,13 @@ class PlayerDataComponent( } } - override fun writeToNbt(tag: NbtCompound) { + override fun writeToNbt(tag: CompoundTag) { tag.put("DART", ENDEC.encodeFully(NbtSerializer::of, Packet(this._modifiers, this.refundablePoints, this.skillPoints, this.isLevelUpNotified))) } - override fun shouldSyncWith(player: ServerPlayerEntity): Boolean = player == this.player + override fun shouldSyncWith(player: ServerPlayer): Boolean = player == this.player - override fun applySyncPacket(buf: PacketByteBuf) { + override fun applySyncPacket(buf: FriendlyByteBuf) { this.readFromNbt(buf.readNbt() ?: return) } } \ No newline at end of file diff --git a/src/main/kotlin/com/bibireden/playerex/ext/EntityAttribute.kt b/src/main/kotlin/com/bibireden/playerex/ext/EntityAttribute.kt index 094c903e..10928a96 100644 --- a/src/main/kotlin/com/bibireden/playerex/ext/EntityAttribute.kt +++ b/src/main/kotlin/com/bibireden/playerex/ext/EntityAttribute.kt @@ -1,9 +1,9 @@ package com.bibireden.playerex.ext -import net.minecraft.entity.attribute.EntityAttribute -import net.minecraft.registry.Registries -import net.minecraft.util.Identifier +import net.minecraft.core.registries.BuiltInRegistries +import net.minecraft.resources.ResourceLocation +import net.minecraft.world.entity.ai.attributes.Attribute -val EntityAttribute.id: Identifier - get() = Registries.ATTRIBUTE.getId(this)!! \ No newline at end of file +val Attribute.id: ResourceLocation + get() = BuiltInRegistries.ATTRIBUTE.getKey(this)!! \ No newline at end of file diff --git a/src/main/kotlin/com/bibireden/playerex/ext/PlayerEntity.kt b/src/main/kotlin/com/bibireden/playerex/ext/PlayerEntity.kt index c5245e11..0b88c9c9 100644 --- a/src/main/kotlin/com/bibireden/playerex/ext/PlayerEntity.kt +++ b/src/main/kotlin/com/bibireden/playerex/ext/PlayerEntity.kt @@ -5,14 +5,14 @@ import com.bibireden.playerex.api.attribute.PlayerEXAttributes import com.bibireden.playerex.components.PlayerEXComponents import com.bibireden.playerex.components.player.IPlayerDataComponent import com.bibireden.playerex.util.PlayerEXUtil -import net.minecraft.entity.player.PlayerEntity +import net.minecraft.world.entity.player.Player -val PlayerEntity.level: Double +val Player.level: Double get() = DataAttributesAPI.getValue(PlayerEXAttributes.LEVEL, this).orElse(1.0) -val PlayerEntity.data: IPlayerDataComponent +val Player.data: IPlayerDataComponent get() = this.getComponent(PlayerEXComponents.PLAYER_DATA) -fun PlayerEntity.canLevelUp(amount: Int = 1): Boolean { +fun Player.canLevelUp(amount: Int = 1): Boolean { return this.experienceLevel >= PlayerEXUtil.getRequiredXpForLevel(this, this.level + amount) } \ No newline at end of file diff --git a/src/main/kotlin/com/bibireden/playerex/factory/DamageFactory.kt b/src/main/kotlin/com/bibireden/playerex/factory/DamageFactory.kt index 197275e8..bd072c9a 100644 --- a/src/main/kotlin/com/bibireden/playerex/factory/DamageFactory.kt +++ b/src/main/kotlin/com/bibireden/playerex/factory/DamageFactory.kt @@ -4,32 +4,32 @@ import com.bibireden.data_attributes.api.DataAttributesAPI import com.bibireden.playerex.api.attribute.PlayerEXAttributes import com.bibireden.playerex.api.damage.DamageFunction import com.bibireden.playerex.api.damage.DamagePredicate -import net.minecraft.entity.AreaEffectCloudEntity -import net.minecraft.entity.damage.DamageTypes -import net.minecraft.entity.effect.StatusEffects -import net.minecraft.entity.projectile.thrown.PotionEntity +import net.minecraft.world.damagesource.DamageTypes +import net.minecraft.world.effect.MobEffects +import net.minecraft.world.entity.AreaEffectCloud +import net.minecraft.world.entity.projectile.ThrownPotion object DamageFactory { fun forEach(registry: (damagePredicate: DamagePredicate, damageFunction: DamageFunction) -> Unit) { - registry.invoke({ _, source, _ -> source.isOf(DamageTypes.ON_FIRE) }, { entity, _, damage -> + registry.invoke({ _, source, _ -> source.`is`(DamageTypes.ON_FIRE) }, { entity, _, damage -> DataAttributesAPI.getValue(PlayerEXAttributes.FIRE_RESISTANCE, entity).map { ((1.0 - (it / 100)) * damage).toFloat() }.orElse(damage) }) - registry.invoke({ _, source, _ -> source.isOf(DamageTypes.FREEZE)}, { living, _, damage -> + registry.invoke({ _, source, _ -> source.`is`(DamageTypes.FREEZE)}, { living, _, damage -> DataAttributesAPI.getValue(PlayerEXAttributes.FREEZE_RESISTANCE, living).map { (damage * (1.0 - it)).toFloat() }.orElse(damage) }) - registry.invoke({ _, source, _ -> source.isOf(DamageTypes.LIGHTNING_BOLT)}, { living, _, damage -> + registry.invoke({ _, source, _ -> source.`is`(DamageTypes.LIGHTNING_BOLT)}, { living, _, damage -> DataAttributesAPI.getValue(PlayerEXAttributes.LIGHTNING_RESISTANCE, living).map { (damage * (1.0 - it)).toFloat() }.orElse(damage) }) registry.invoke( - { living, source, damage -> living.hasStatusEffect(StatusEffects.POISON) && source.isOf(DamageTypes.MAGIC) && damage <= 1.0F }, + { living, source, damage -> living.hasEffect(MobEffects.POISON) && source.`is`(DamageTypes.MAGIC) && damage <= 1.0F }, {living, _, damage -> DataAttributesAPI.getValue(PlayerEXAttributes.POISON_RESISTANCE, living).map { (damage * (1.0 - it)).toFloat() }.orElse(damage) } ) - registry.invoke({_, source, _ -> source.isOf(DamageTypes.WITHER) || (source.isOf(DamageTypes.INDIRECT_MAGIC) && (source.source is PotionEntity || source.source is AreaEffectCloudEntity))}, { + registry.invoke({_, source, _ -> source.`is`(DamageTypes.WITHER) || (source.`is`(DamageTypes.INDIRECT_MAGIC) && ((source.directEntity is ThrownPotion) || (source.directEntity is AreaEffectCloud))) }, { living, source, damage -> DataAttributesAPI.getValue(PlayerEXAttributes.WITHER_RESISTANCE, living).map { - if (source.isOf(DamageTypes.WITHER) && living.isUndead) return@map 0.0F - if (source.isOf(DamageTypes.INDIRECT_MAGIC) && source.source is PotionEntity && living.isUndead) return@map damage + if (source.`is`(DamageTypes.WITHER) && living.isInvertedHealAndHarm) return@map 0.0F + if (source.`is`(DamageTypes.INDIRECT_MAGIC) && source.directEntity is ThrownPotion && living.isInvertedHealAndHarm) return@map damage (damage * (1.0 - it)).toFloat() }.orElse(damage) }) diff --git a/src/main/kotlin/com/bibireden/playerex/factory/EventFactory.kt b/src/main/kotlin/com/bibireden/playerex/factory/EventFactory.kt index ba8bbe1c..82860c96 100644 --- a/src/main/kotlin/com/bibireden/playerex/factory/EventFactory.kt +++ b/src/main/kotlin/com/bibireden/playerex/factory/EventFactory.kt @@ -5,16 +5,16 @@ import com.bibireden.playerex.PlayerEX import com.bibireden.playerex.api.attribute.PlayerEXAttributes import com.bibireden.playerex.components.PlayerEXComponents import com.bibireden.playerex.registry.DamageModificationRegistry -import net.minecraft.entity.Entity -import net.minecraft.entity.LivingEntity -import net.minecraft.entity.damage.DamageSource -import net.minecraft.entity.effect.StatusEffects -import net.minecraft.entity.player.PlayerEntity -import net.minecraft.entity.projectile.PersistentProjectileEntity -import net.minecraft.server.network.ServerPlayerEntity +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.player.Player +import net.minecraft.world.entity.projectile.AbstractArrow object EventFactory { - fun reset(oldPlayer: ServerPlayerEntity, newPlayer: ServerPlayerEntity, isAlive: Boolean) + fun reset(oldPlayer: ServerPlayer, newPlayer: ServerPlayer, isAlive: Boolean) { PlayerEXComponents.PLAYER_DATA.get(newPlayer).reset(if (PlayerEX.CONFIG.resetOnDeath) 0 else 100) } @@ -26,16 +26,16 @@ object EventFactory { fun healthRegeneration(livingEntity: LivingEntity) { - if (!livingEntity.world.isClient) { - val healthRegenerationOption = DataAttributesAPI.getValue(PlayerEXAttributes.HEALTH_REGENERATION, livingEntity); + if (!livingEntity.level().isClientSide()) { + val healthRegenerationOption = DataAttributesAPI.getValue(PlayerEXAttributes.HEALTH_REGENERATION, livingEntity) if (healthRegenerationOption.isPresent) { - val healthRegeneration = healthRegenerationOption.get(); + val healthRegeneration = healthRegenerationOption.get() if (healthRegeneration > 0.0 && livingEntity.health < livingEntity.maxHealth) { - livingEntity.heal(healthRegeneration.toFloat()); + livingEntity.heal(healthRegeneration.toFloat()) } return @@ -64,16 +64,16 @@ object EventFactory { { if (original == 0.0F) { - return true; + return true } - val origin: Entity? = source.source; - val attacker: Entity? = source.attacker; + val origin: Entity? = source.directEntity + val attacker: Entity? = source.entity - if (attacker is LivingEntity && (origin is LivingEntity || origin is PersistentProjectileEntity)) + if (attacker is LivingEntity && (origin is LivingEntity || origin is AbstractArrow)) { DataAttributesAPI.getValue(PlayerEXAttributes.LIFESTEAL, livingEntity).ifPresent { - attacker.heal((original * it * 10.0).toFloat()); + attacker.heal((original * it * 10.0).toFloat()) } } @@ -81,37 +81,37 @@ object EventFactory { if (evasionOption.isPresent) { - val chance = livingEntity.random.nextFloat(); - return !(chance < evasionOption.get() && origin is PersistentProjectileEntity); + val chance = livingEntity.random.nextFloat() + return !(chance < evasionOption.get() && origin is AbstractArrow) } return true } - fun onCritAttack(player: PlayerEntity, target: Entity, amount: Float): Float + fun onCritAttack(player: Player, target: Entity, amount: Float): Float { - if (target !is LivingEntity) return amount; + if (target !is LivingEntity) return amount - val meleeCritOption = DataAttributesAPI.getValue(PlayerEXAttributes.MELEE_CRITICAL_DAMAGE, player); + val meleeCritOption = DataAttributesAPI.getValue(PlayerEXAttributes.MELEE_CRITICAL_DAMAGE, player) if (meleeCritOption.isPresent) { - return (amount * (1.0 + (meleeCritOption.get() * 10.0)) / 1.5).toFloat(); + return (amount * (1.0 + (meleeCritOption.get() * 10.0)) / 1.5).toFloat() } return amount } - fun attackIsCrit(player: PlayerEntity, target: Entity, original: Boolean): Boolean + fun attackIsCrit(player: Player, target: Entity, original: Boolean): Boolean { - if (target !is LivingEntity) return original; + if (target !is LivingEntity) return original - val critChanceOptional = DataAttributesAPI.getValue(PlayerEXAttributes.MELEE_CRITICAL_CHANCE, player); + val critChanceOptional = DataAttributesAPI.getValue(PlayerEXAttributes.MELEE_CRITICAL_CHANCE, player) if (critChanceOptional.isPresent) { - val chance = player.random.nextFloat(); - return (chance < critChanceOptional.get()) && !player.isClimbing && !player.hasStatusEffect(StatusEffects.BLINDNESS) && !player.hasVehicle(); + val chance = player.random.nextFloat() + return (chance < critChanceOptional.get()) && !player.onClimbable() && !player.hasEffect(MobEffects.BLINDNESS) && !player.isPassenger } return original diff --git a/src/main/kotlin/com/bibireden/playerex/factory/PlaceholderFactory.kt b/src/main/kotlin/com/bibireden/playerex/factory/PlaceholderFactory.kt index a0055f68..d5ac14f6 100644 --- a/src/main/kotlin/com/bibireden/playerex/factory/PlaceholderFactory.kt +++ b/src/main/kotlin/com/bibireden/playerex/factory/PlaceholderFactory.kt @@ -8,14 +8,14 @@ import com.bibireden.playerex.api.attribute.PlayerEXAttributes import com.bibireden.playerex.ext.level import eu.pb4.placeholders.api.PlaceholderHandler import eu.pb4.placeholders.api.PlaceholderResult +import net.minecraft.resources.ResourceLocation import net.minecraft.server.MinecraftServer -import net.minecraft.server.network.ServerPlayerEntity -import net.minecraft.util.Identifier -import net.minecraft.util.math.MathHelper +import net.minecraft.server.level.ServerPlayer +import net.minecraft.util.Mth import kotlin.math.max object PlaceholderFactory { - val STORE: MutableMap = mutableMapOf(); + val STORE: MutableMap = mutableMapOf(); private fun nameLevelPair(server: MinecraftServer, namesIn: Collection, indexIn: Int): Pair { @@ -35,7 +35,7 @@ object PlaceholderFactory { names.sortWith(Comparator.comparing { (_, level) -> level }) - val j = MathHelper.clamp(indexIn, 1, names.size) + val j = Mth.clamp(indexIn, 1, names.size) return names[names.size - j] } @@ -71,13 +71,13 @@ object PlaceholderFactory { } init { - val levelId = Identifier.of(PlayerEX.MOD_ID, "level") - val nameTopId = Identifier.of(PlayerEX.MOD_ID, "name_top") - val levelTopId = Identifier.of(PlayerEX.MOD_ID, "level_top") + val levelId = ResourceLocation.tryBuild(PlayerEX.MOD_ID, "level") + val nameTopId = ResourceLocation.tryBuild(PlayerEX.MOD_ID, "name_top") + val levelTopId = ResourceLocation.tryBuild(PlayerEX.MOD_ID, "level_top") if (levelId != null) { STORE[levelId] = PlaceholderHandler { ctx, _ -> - val player: ServerPlayerEntity? = ctx?.player + val player: ServerPlayer? = ctx?.player player ?: return@PlaceholderHandler PlaceholderResult.invalid("No player!"); diff --git a/src/main/kotlin/com/bibireden/playerex/factory/RefundFactory.kt b/src/main/kotlin/com/bibireden/playerex/factory/RefundFactory.kt index c62a5c22..24bb810c 100644 --- a/src/main/kotlin/com/bibireden/playerex/factory/RefundFactory.kt +++ b/src/main/kotlin/com/bibireden/playerex/factory/RefundFactory.kt @@ -2,11 +2,11 @@ package com.bibireden.playerex.factory import com.bibireden.playerex.api.attribute.PlayerEXAttributes import com.bibireden.playerex.components.player.IPlayerDataComponent -import net.minecraft.entity.player.PlayerEntity +import net.minecraft.world.entity.player.Player import java.util.function.Consumer object RefundFactory { - fun forEach(registry: Consumer<(IPlayerDataComponent, PlayerEntity) -> Double>) { + fun forEach(registry: Consumer<(IPlayerDataComponent, Player) -> Double>) { registry.accept { data, player -> data.get(PlayerEXAttributes.CONSTITUTION) } registry.accept { data, player -> data.get(PlayerEXAttributes.STRENGTH) } registry.accept { data, player -> data.get(PlayerEXAttributes.DEXTERITY) } diff --git a/src/main/kotlin/com/bibireden/playerex/factory/ServerNetworkingFactory.kt b/src/main/kotlin/com/bibireden/playerex/factory/ServerNetworkingFactory.kt index fd6b7f45..7372bca9 100644 --- a/src/main/kotlin/com/bibireden/playerex/factory/ServerNetworkingFactory.kt +++ b/src/main/kotlin/com/bibireden/playerex/factory/ServerNetworkingFactory.kt @@ -5,19 +5,19 @@ import com.bibireden.playerex.networking.NetworkingPackets import com.bibireden.playerex.networking.types.NotificationType import net.fabricmc.fabric.api.networking.v1.PacketSender import net.fabricmc.fabric.api.networking.v1.ServerLoginNetworking -import net.minecraft.entity.player.PlayerEntity import net.minecraft.server.MinecraftServer -import net.minecraft.server.network.ServerLoginNetworkHandler +import net.minecraft.server.network.ServerLoginPacketListenerImpl +import net.minecraft.world.entity.player.Player object ServerNetworkingFactory { @JvmStatic - fun onLoginQueryStart(handler: ServerLoginNetworkHandler, server: MinecraftServer, sender: PacketSender, synchronizer: ServerLoginNetworking.LoginSynchronizer) { + fun onLoginQueryStart(handler: ServerLoginPacketListenerImpl, server: MinecraftServer, sender: PacketSender, synchronizer: ServerLoginNetworking.LoginSynchronizer) { // todo: requires a config implementation :: requires synchronization at this point, but i think this is automatically handled by owo so probably no need for this, so what's the point of even including this function in the first place i'm going to to crash out } /** Notifies the given player about a specific [NotificationType]. */ @JvmStatic - fun notify(player: PlayerEntity, type: NotificationType) { + fun notify(player: Player, type: NotificationType) { NetworkingChannels.NOTIFICATIONS.serverHandle(player).send(NetworkingPackets.Notify(type)) } } \ No newline at end of file diff --git a/src/main/kotlin/com/bibireden/playerex/keys/LevelKey.kt b/src/main/kotlin/com/bibireden/playerex/keys/LevelKey.kt index c2d48feb..8e97d91c 100644 --- a/src/main/kotlin/com/bibireden/playerex/keys/LevelKey.kt +++ b/src/main/kotlin/com/bibireden/playerex/keys/LevelKey.kt @@ -4,20 +4,19 @@ import com.bibireden.data_attributes.api.DataAttributesAPI import com.bibireden.opc.api.CachedPlayerKey import com.bibireden.playerex.PlayerEX import com.bibireden.playerex.api.attribute.PlayerEXAttributes -import net.minecraft.nbt.NbtCompound -import net.minecraft.server.network.ServerPlayerEntity -import kotlin.jvm.optionals.getOrNull +import net.minecraft.nbt.CompoundTag +import net.minecraft.server.level.ServerPlayer class LevelKey : CachedPlayerKey(PlayerEX.id("level")) { - override fun get(player: ServerPlayerEntity): Int { + override fun get(player: ServerPlayer): Int { return DataAttributesAPI.getValue(PlayerEXAttributes.LEVEL, player).map(Double::toInt).orElse(0) } - override fun readFromNbt(tag: NbtCompound): Int { + override fun readFromNbt(tag: CompoundTag): Int { return tag.getInt("level") } - override fun writeToNbt(tag: NbtCompound, value: Any) { + override fun writeToNbt(tag: CompoundTag, value: Any) { if (value is Int) tag.putInt("level", value) } } \ No newline at end of file diff --git a/src/main/kotlin/com/bibireden/playerex/networking/NetworkingPackets.kt b/src/main/kotlin/com/bibireden/playerex/networking/NetworkingPackets.kt index 64810d03..772d4512 100644 --- a/src/main/kotlin/com/bibireden/playerex/networking/NetworkingPackets.kt +++ b/src/main/kotlin/com/bibireden/playerex/networking/NetworkingPackets.kt @@ -2,8 +2,7 @@ package com.bibireden.playerex.networking import com.bibireden.playerex.networking.types.UpdatePacketType import com.bibireden.playerex.networking.types.NotificationType -import net.minecraft.util.Identifier - +import net.minecraft.resources.ResourceLocation object NetworkingPackets { /** @@ -17,7 +16,7 @@ object NetworkingPackets { * Possibility will be dictated based on the [UpdatePacketType] */ @JvmRecord - data class Update(val type: UpdatePacketType, val id: Identifier, val amount: Int) + data class Update(val type: UpdatePacketType, val id: ResourceLocation, val amount: Int) /** Packet specifically for handling leveling events. Provides the amount of levels the client intends to increase by. */ @JvmRecord diff --git a/src/main/kotlin/com/bibireden/playerex/registry/RefundConditionRegistry.kt b/src/main/kotlin/com/bibireden/playerex/registry/RefundConditionRegistry.kt index f929ba5d..bd2491e8 100644 --- a/src/main/kotlin/com/bibireden/playerex/registry/RefundConditionRegistry.kt +++ b/src/main/kotlin/com/bibireden/playerex/registry/RefundConditionRegistry.kt @@ -1,9 +1,9 @@ package com.bibireden.playerex.registry import com.bibireden.playerex.components.player.IPlayerDataComponent -import net.minecraft.entity.player.PlayerEntity +import net.minecraft.world.entity.player.Player -typealias RefundCondition = (IPlayerDataComponent, PlayerEntity) -> Double +typealias RefundCondition = (IPlayerDataComponent, Player) -> Double object RefundConditionRegistry { private val entries: MutableList = mutableListOf() diff --git a/src/main/kotlin/com/bibireden/playerex/util/PlayerEXUtil.kt b/src/main/kotlin/com/bibireden/playerex/util/PlayerEXUtil.kt index 7767dcad..039d7675 100644 --- a/src/main/kotlin/com/bibireden/playerex/util/PlayerEXUtil.kt +++ b/src/main/kotlin/com/bibireden/playerex/util/PlayerEXUtil.kt @@ -3,7 +3,7 @@ package com.bibireden.playerex.util import com.bibireden.data_attributes.api.util.Maths import com.bibireden.playerex.PlayerEX import com.bibireden.playerex.ext.level -import net.minecraft.entity.player.PlayerEntity +import net.minecraft.world.entity.player.Player import net.objecthunter.exp4j.Expression import net.objecthunter.exp4j.ExpressionBuilder import net.objecthunter.exp4j.function.Function @@ -30,7 +30,7 @@ object PlayerEXUtil { @JvmStatic /** Computes the experience cost of the provided level. */ - fun getRequiredXpForLevel(player: PlayerEntity, target: Double): Int { + fun getRequiredXpForLevel(player: Player, target: Double): Int { val steps = (target - player.level).toInt() if (steps <= 0) return 0 @@ -45,5 +45,5 @@ object PlayerEXUtil { /** todo: document, none evident on former, resolve if orElse is needed here, and if we can do nullable or not without drastically changing things */ @JvmStatic - fun getRequiredXpForNextLevel(player: PlayerEntity): Int = getRequiredXpForLevel(player, player.level + 1) + fun getRequiredXpForNextLevel(player: Player): Int = getRequiredXpForLevel(player, player.level + 1) } \ No newline at end of file diff --git a/src/main/resources/playerex.mixins.json b/src/main/resources/playerex.mixins.json index 03cde5cf..c1a9805d 100644 --- a/src/main/resources/playerex.mixins.json +++ b/src/main/resources/playerex.mixins.json @@ -1,17 +1,17 @@ { - "required": true, - "package": "com.bibireden.playerex.mixin", - "compatibilityLevel": "JAVA_17", - "mixins": [ - "ExperienceOrbEntityMixin", - "LivingEntityMixin", - "PersistentProjectileEntityMixin", - "PlayerEntityMixin", - "PlayerInventoryMixin", - "ServerPlayerEntityMixin", - "ServerWorldMixin" - ], - "injectors": { - "defaultRequire": 1 + "required": true, + "package": "com.bibireden.playerex.mixin", + "compatibilityLevel": "JAVA_17", + "mixins": [ + "AbstractArrowMixin", + "ExperienceOrbMixin", + "InventoryMixin", + "LivingEntityMixin", + "PlayerMixin", + "ServerLevelMixin", + "ServerPlayerMixin" + ], + "injectors": { + "defaultRequire": 1 } } \ No newline at end of file From 5914ffe328ecc41fe2bf57cf676ebcbf66e3f3e4 Mon Sep 17 00:00:00 2001 From: Data Encoded <81109563+DataEncoded@users.noreply.github.com> Date: Tue, 30 Jul 2024 14:31:27 -0500 Subject: [PATCH 02/11] merge 1.20.1/fabric dev.aea (#18) * [deps] Update AEA to newest * [semver] Bump alpha number --- gradle.properties | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gradle.properties b/gradle.properties index d9265d24..a8b72a0f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -17,14 +17,14 @@ parchment_version=1.20.1:2023.09.03 quilt_mappings_version=23 # Mod Properties -mod_version=4.0.0-alpha.6+1.20.1 +mod_version=4.0.0-alpha.7+1.20.1 maven_group=com.bibireden.playerex archives_base_name=playerex-directors-cut # Dependencies fabric_version=0.92.2+1.20.1 cardinal_components_version=5.2.2 -additional_entity_attributes_version=1.7.0+1.20.0 +additional_entity_attributes_version=1.7.4+1.20.0 all_the_trims_version=3.4.2 placeholder_api_version=2.1.1+1.20 ranged_weapon_api_version=1.1.2+1.20.1 @@ -41,4 +41,4 @@ endec_version=0.1.7 endec_gson_version=0.1.4 endec_netty_version=0.1.3 -exp4j_version=0.4.8 \ No newline at end of file +exp4j_version=0.4.8 From 5f5617e062467461665767ac4cea98a641b9e683 Mon Sep 17 00:00:00 2001 From: Bibi Reden Date: Fri, 2 Aug 2024 02:14:21 -0500 Subject: [PATCH 03/11] Update to newer OfflinePlayerCache & UI Updates (along with mixin changes) (#19) * Implement new OPC * Rewrote `AbstractArrowMixin` & `ExperienceOrbMixin` * Adjust math in `AbstractArrowMixin` * Nitpick mixins, remove `ServerLevelMixin` * Nitpick `ServerPlayerMixin` * Add CL, tweak `AbstractArrowMixin` * Redo menu logic * Step version -> alpha.8 * Add ordering to UI to have certain elements display first * Added in proper type for screen * Forgot a `ResourceLocation` * Make API funcs @JvmStatic * Step up OPC, JvmFields/JvmStatics * Change workflow --- .github/workflows/build-and-deploy.yml | 2 +- CHANGELOG.md | 7 +- gradle.properties | 4 +- .../registry/PlayerEXMenuRegistry.java | 52 +++++++++++++-- .../com/bibireden/playerex/PlayerEXClient.kt | 7 +- .../bibireden/playerex/ui/PlayerEXScreen.kt | 7 +- .../playerex/ui/components/MenuComponent.kt | 20 ++++-- .../playerex/ui/menus/ConceptMenu.kt | 14 ---- .../ui/menus/PlayerEXAttributesMenu.kt | 27 +++----- .../playerex/ui/util/FormattingPredicates.kt | 16 ++++- .../playerex/mixin/AbstractArrowMixin.java | 65 +++++++------------ .../playerex/mixin/ExperienceOrbMixin.java | 7 +- .../playerex/mixin/InventoryMixin.java | 2 +- .../playerex/mixin/LivingEntityMixin.java | 4 +- .../bibireden/playerex/mixin/PlayerMixin.java | 1 - .../playerex/mixin/ServerLevelMixin.java | 7 -- .../playerex/mixin/ServerPlayerMixin.java | 21 +++--- .../kotlin/com/bibireden/playerex/PlayerEX.kt | 17 ++++- .../com/bibireden/playerex/api/PlayerEXAPI.kt | 12 +--- .../playerex/api/PlayerEXCachedKeys.kt | 16 ++++- .../playerex/api/PlayerEXModifiers.kt | 1 + .../api/attribute/DefaultAttributeImpl.kt | 2 + .../api/attribute/PlayerEXAttributes.kt | 3 +- .../playerex/api/event/PlayerEXSoundEvents.kt | 3 + .../playerex/api/event/PlayerEntityEvents.kt | 1 - .../bibireden/playerex/compat/CompatUtils.kt | 2 + .../playerex/factory/PlaceholderFactory.kt | 32 ++++----- .../com/bibireden/playerex/keys/LevelKey.kt | 22 ------- .../playerex/networking/NetworkingChannels.kt | 2 + .../registry/DamageModificationRegistry.kt | 2 + .../bibireden/playerex/util/PlayerEXUtil.kt | 1 + src/main/resources/playerex.mixins.json | 1 - 32 files changed, 204 insertions(+), 176 deletions(-) delete mode 100644 src/client/kotlin/com/bibireden/playerex/ui/menus/ConceptMenu.kt delete mode 100644 src/main/java/com/bibireden/playerex/mixin/ServerLevelMixin.java delete mode 100644 src/main/kotlin/com/bibireden/playerex/keys/LevelKey.kt diff --git a/.github/workflows/build-and-deploy.yml b/.github/workflows/build-and-deploy.yml index 57013c1c..bb61f224 100644 --- a/.github/workflows/build-and-deploy.yml +++ b/.github/workflows/build-and-deploy.yml @@ -52,7 +52,7 @@ jobs: if: github.ref == 'refs/heads/${{ env.BRANCH_PREFIX }}' id: minecraft_version run: | - minecraft_version_val=$(grep "mod_version" gradle.properties | cut -d'+' -f2 | tr -d '\n') + minecraft_version_val=$(grep "mod_version" gradle.properties | cut -d'=' -f2 | cut -d'-' -f1 | tr -d '\n') echo "minecraft_version=$minecraft_version_val" >> $GITHUB_OUTPUT - name: deploy with mc-publish if: github.ref == 'refs/heads/${{ env.BRANCH_PREFIX }}' diff --git a/CHANGELOG.md b/CHANGELOG.md index 970d80e9..6e1aa040 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,4 @@ -## Fixes & Changes ⚒️ -- Fixed issues with `alpha.5` having an outdated variant of the previous. -- Migrated to mojmappings. \ No newline at end of file +## Changes ⚒️ +- Updated to a newer build of `OfflinePlayerCache`. +- Changed some more internals. +- Reimplemented original calculation of projectile critical chance. \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index a8b72a0f..6cabbfe7 100644 --- a/gradle.properties +++ b/gradle.properties @@ -17,7 +17,7 @@ parchment_version=1.20.1:2023.09.03 quilt_mappings_version=23 # Mod Properties -mod_version=4.0.0-alpha.7+1.20.1 +mod_version=4.0.0+1.20.1-alpha.8 maven_group=com.bibireden.playerex archives_base_name=playerex-directors-cut @@ -30,7 +30,7 @@ placeholder_api_version=2.1.1+1.20 ranged_weapon_api_version=1.1.2+1.20.1 # in-house -opc_version=1.0.0+1.20.1-fabric +opc_version=2.0.0+1.20.1-beta.1-fabric data_attributes_version=2.0.0-beta.7+1.20.1-fabric # owo diff --git a/src/client/java/com/bibireden/playerex/registry/PlayerEXMenuRegistry.java b/src/client/java/com/bibireden/playerex/registry/PlayerEXMenuRegistry.java index 1e67dfa8..ac0f7202 100644 --- a/src/client/java/com/bibireden/playerex/registry/PlayerEXMenuRegistry.java +++ b/src/client/java/com/bibireden/playerex/registry/PlayerEXMenuRegistry.java @@ -1,23 +1,67 @@ package com.bibireden.playerex.registry; import com.bibireden.playerex.ui.components.MenuComponent; +import com.bibireden.playerex.ui.PlayerEXScreen; +import kotlin.Pair; +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.resources.ResourceLocation; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.stream.Collectors; +/** + * Used to register {@link MenuComponent}'s to the {@link PlayerEXScreen}. + * This allows you to build a UI layer with PlayerEX + * and access component data for the {@link LocalPlayer}. + */ public final class PlayerEXMenuRegistry { @NotNull - private static final List> ENTRIES = new ArrayList<>(); + private static final List>> ENTRIES = new ArrayList<>(); + + @NotNull + private static final HashMap PRIORITY_ORDER = new HashMap<>(); /** * Registers a {@link MenuComponent} to the registry, - * which will be applied to the {@link com.bibireden.playerex.ui.PlayerEXScreen} as a page. + * which will be applied to the {@link PlayerEXScreen} as a page. */ - public static void register(@NotNull Class menu) { ENTRIES.add(menu); } + public static void register(ResourceLocation id, @NotNull Class menu) { + Integer position = PRIORITY_ORDER.get(id.getNamespace()); + if (position != null) { + for (int i = 0; i < ENTRIES.size(); i++) { + ResourceLocation entryId = ENTRIES.get(i).getFirst(); + if (PRIORITY_ORDER.get(entryId.getNamespace()) >= position) { + position = i + 1; + } + } + ENTRIES.add(position, new Pair<>(id, menu)); + } + else { + ENTRIES.add(new Pair<>(id, menu)); + } + } @NotNull - public static List> get() { + public static List>> get() { return ENTRIES; } + + @NotNull + public static List getIds() { + return ENTRIES.stream().map(Pair::component1).toList(); + } + + @NotNull + public static List> getDefs() { + return ENTRIES.stream().map(Pair::component2).collect(Collectors.toUnmodifiableList()); + } + + static { + PRIORITY_ORDER.put("playerex", 0); + PRIORITY_ORDER.put("relicex", 1); + PRIORITY_ORDER.put("wizardex", 2); + } } diff --git a/src/client/kotlin/com/bibireden/playerex/PlayerEXClient.kt b/src/client/kotlin/com/bibireden/playerex/PlayerEXClient.kt index 73a684bd..5a5d3008 100644 --- a/src/client/kotlin/com/bibireden/playerex/PlayerEXClient.kt +++ b/src/client/kotlin/com/bibireden/playerex/PlayerEXClient.kt @@ -52,14 +52,13 @@ object PlayerEXClient : ClientModInitializer { } } - PlayerEXMenuRegistry.register(PlayerEXAttributesMenu::class.java) + PlayerEXMenuRegistry.register(PlayerEX.id("attributes"), PlayerEXAttributesMenu::class.java) ClientTickEvents.END_CLIENT_TICK.register { client -> if (PlayerEX.CONFIG.disableUI) return@register + while (KEYBINDING_MAIN_SCREEN.consumeClick()) { - if (client.screen == null) { - client.setScreen(PlayerEXScreen()) - } + if (client.screen == null) client.setScreen(PlayerEXScreen()) } } } diff --git a/src/client/kotlin/com/bibireden/playerex/ui/PlayerEXScreen.kt b/src/client/kotlin/com/bibireden/playerex/ui/PlayerEXScreen.kt index 65fe26eb..f1d10c6c 100644 --- a/src/client/kotlin/com/bibireden/playerex/ui/PlayerEXScreen.kt +++ b/src/client/kotlin/com/bibireden/playerex/ui/PlayerEXScreen.kt @@ -128,9 +128,10 @@ class PlayerEXScreen : BaseUIModelScreen(FlowLayout::class.java, Dat val nextPage = rootComponent.childById(ButtonComponent::class, "next")!! val exit = rootComponent.childById(ButtonComponent::class, "exit")!! - PlayerEXMenuRegistry.get().forEach { - val instance = it.getDeclaredConstructor().newInstance() - instance.build(player, this.uiAdapter, player.data) + PlayerEXMenuRegistry.get().forEach { (_, clazz) -> + val instance = clazz.getDeclaredConstructor().newInstance() + instance.init(minecraft!!, this, player.data) + instance.build(content) pages.add(instance) } diff --git a/src/client/kotlin/com/bibireden/playerex/ui/components/MenuComponent.kt b/src/client/kotlin/com/bibireden/playerex/ui/components/MenuComponent.kt index 5f766354..eaa3aefe 100644 --- a/src/client/kotlin/com/bibireden/playerex/ui/components/MenuComponent.kt +++ b/src/client/kotlin/com/bibireden/playerex/ui/components/MenuComponent.kt @@ -3,11 +3,10 @@ package com.bibireden.playerex.ui.components import com.bibireden.playerex.components.player.IPlayerDataComponent import com.bibireden.playerex.ui.PlayerEXScreen import io.wispforest.owo.ui.container.FlowLayout -import io.wispforest.owo.ui.core.OwoUIAdapter import io.wispforest.owo.ui.core.Sizing import io.wispforest.owo.util.EventSource import io.wispforest.owo.util.EventStream -import net.minecraft.client.player.LocalPlayer +import net.minecraft.client.Minecraft import net.minecraft.world.entity.ai.attributes.Attribute import org.jetbrains.annotations.ApiStatus @@ -19,20 +18,31 @@ import org.jetbrains.annotations.ApiStatus */ @ApiStatus.OverrideOnly abstract class MenuComponent(horizontalSizing: Sizing = Sizing.fill(100), verticalSizing: Sizing = Sizing.fill(100), algorithm: Algorithm) : FlowLayout(horizontalSizing, verticalSizing, algorithm) { + protected var client: Minecraft? = null + protected var screen: PlayerEXScreen? = null + protected var playerComponent: IPlayerDataComponent? = null + val onLevelUpdatedEvents = OnLevelUpdated.stream val onAttributeUpdatedEvents = OnAttributeUpdated.stream val onLevelUpdated: EventSource = onLevelUpdatedEvents.source() val onAttributeUpdated: EventSource = onAttributeUpdatedEvents.source() - /** When the [PlayerEXScreen] is ready to be constructed, this function (if the component is registered) will be called.*/ - abstract fun build(player: LocalPlayer, adapter: OwoUIAdapter, component: IPlayerDataComponent) + /** Initializes this menu. Normally is called around the time it is mounted onto the [PlayerEXScreen]. */ + fun init(minecraft: Minecraft, screen: PlayerEXScreen, component: IPlayerDataComponent) { + this.client = minecraft + this.screen = screen + this.playerComponent = component + } + + /** Where ui-based logic should occur at, built off of the root of the screen's provided content area. */ + abstract fun build(rootComponent: FlowLayout) fun interface OnLevelUpdated { fun onLevelUpdated(level: Int) companion object { - val stream: EventStream get() = EventStream { subscribers -> + val stream: EventStream = EventStream { subscribers -> OnLevelUpdated { level -> subscribers.forEach { it.onLevelUpdated(level) } } } } diff --git a/src/client/kotlin/com/bibireden/playerex/ui/menus/ConceptMenu.kt b/src/client/kotlin/com/bibireden/playerex/ui/menus/ConceptMenu.kt deleted file mode 100644 index 71d09e9d..00000000 --- a/src/client/kotlin/com/bibireden/playerex/ui/menus/ConceptMenu.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.bibireden.playerex.ui.menus - -import com.bibireden.playerex.components.player.IPlayerDataComponent -import com.bibireden.playerex.ui.components.MenuComponent -import io.wispforest.owo.ui.container.FlowLayout -import io.wispforest.owo.ui.core.OwoUIAdapter -import net.minecraft.client.player.LocalPlayer -import org.jetbrains.annotations.ApiStatus - -@ApiStatus.Internal -class ConceptMenu : MenuComponent(algorithm = Algorithm.VERTICAL) { - override fun build(player: LocalPlayer, adapter: OwoUIAdapter, component: IPlayerDataComponent) { - } -} \ No newline at end of file diff --git a/src/client/kotlin/com/bibireden/playerex/ui/menus/PlayerEXAttributesMenu.kt b/src/client/kotlin/com/bibireden/playerex/ui/menus/PlayerEXAttributesMenu.kt index def9eb03..c57a14ac 100644 --- a/src/client/kotlin/com/bibireden/playerex/ui/menus/PlayerEXAttributesMenu.kt +++ b/src/client/kotlin/com/bibireden/playerex/ui/menus/PlayerEXAttributesMenu.kt @@ -20,15 +20,12 @@ import io.wispforest.owo.ui.container.Containers import io.wispforest.owo.ui.container.FlowLayout import io.wispforest.owo.ui.core.* import net.fabric_extras.ranged_weapon.api.EntityAttributes_RangedWeapon -import net.minecraft.client.player.LocalPlayer import net.minecraft.core.registries.BuiltInRegistries import net.minecraft.world.entity.ai.attributes.Attributes import net.minecraft.world.entity.player.Player import net.minecraft.network.chat.Component import org.jetbrains.annotations.ApiStatus -// todo: cache buttons/certain UI elements - @ApiStatus.Internal class PlayerEXAttributesMenu : MenuComponent(algorithm = Algorithm.HORIZONTAL) { private val MELEE_COMBAT_STATS: List> = listOf( @@ -41,7 +38,7 @@ class PlayerEXAttributesMenu : MenuComponent(algorithm = Algorithm.HORIZONTAL) { private val RANGED_COMBAT_STATS: List> = listOf( EntityAttributeSupplier(PlayerEXAttributes.RANGED_CRITICAL_DAMAGE.id) to FormattingPredicates.PERCENTAGE_MULTIPLY, EntityAttributeSupplier(PlayerEXAttributes.RANGED_CRITICAL_CHANCE.id) to FormattingPredicates.PERCENTAGE_MULTIPLY, - EntityAttributeSupplier(EntityAttributes_RangedWeapon.HASTE.id) to FormattingPredicates.fromBaseValue(EntityAttributes_RangedWeapon.HASTE.attribute), + EntityAttributeSupplier(EntityAttributes_RangedWeapon.HASTE.id) to FormattingPredicates.fromBaseValue(EntityAttributes_RangedWeapon.HASTE.attribute, true), EntityAttributeSupplier(EntityAttributes_RangedWeapon.DAMAGE.id) to FormattingPredicates.NORMAL, ) @@ -73,18 +70,11 @@ class PlayerEXAttributesMenu : MenuComponent(algorithm = Algorithm.HORIZONTAL) { private fun onAttributeUpdate() { // refresh all attribute labels this.forEachDescendant { component -> - // todo: use derived interface to check instance - if (component is AttributeComponent) { - component.refresh() - return@forEachDescendant - } - if (component is AttributeLabelComponent) { - component.refresh() - return@forEachDescendant - } - if (component is AttributeListEntryComponent) { - component.refresh() - return@forEachDescendant + // a bit more tolerable + when (component) { + is AttributeComponent -> component.refresh() + is AttributeLabelComponent -> component.refresh() + is AttributeListEntryComponent -> component.refresh() } } } @@ -106,7 +96,10 @@ class PlayerEXAttributesMenu : MenuComponent(algorithm = Algorithm.HORIZONTAL) { } - override fun build(player: LocalPlayer, adapter: OwoUIAdapter, component: IPlayerDataComponent) { + override fun build(rootComponent: FlowLayout) { + val player = client?.player ?: return + val component = playerComponent ?: return + child(Containers.verticalScroll( Sizing.fill(45), Sizing.fill(100), diff --git a/src/client/kotlin/com/bibireden/playerex/ui/util/FormattingPredicates.kt b/src/client/kotlin/com/bibireden/playerex/ui/util/FormattingPredicates.kt index 12f6d487..b8b7d45d 100644 --- a/src/client/kotlin/com/bibireden/playerex/ui/util/FormattingPredicates.kt +++ b/src/client/kotlin/com/bibireden/playerex/ui/util/FormattingPredicates.kt @@ -5,17 +5,27 @@ import net.minecraft.world.entity.ai.attributes.Attribute import kotlin.math.round object FormattingPredicates { + @JvmField val NORMAL: FormattingPredicate = { "%.2f".format(it) } - val PERCENT: FormattingPredicate = { "${it.toInt()}%" } + @JvmField val PERCENTAGE_MULTIPLY: FormattingPredicate = { "${(it * 100.0).toInt()}%" } + @JvmField val PERCENTAGE_DIVIDE: FormattingPredicate = { "${(it / 100.0).toInt()}%" } - fun fromBaseValue(attribute: Attribute): FormattingPredicate { + /** + * Bases calculation and positive/negative evaluation using the [Attribute]'s base as a metric. + * + * For example, if an attribute's base value was 100, + * and the current value of a player's attribute was 150, it is a `+50` increase. + * */ + @JvmStatic + fun fromBaseValue(attribute: Attribute, percentage: Boolean): FormattingPredicate { return { val result = round(it - attribute.defaultValue).toInt() var text = "$result" if (result > 0) text = "+$result" - text + "%" + if (percentage) text += "%" + text } } } \ No newline at end of file diff --git a/src/main/java/com/bibireden/playerex/mixin/AbstractArrowMixin.java b/src/main/java/com/bibireden/playerex/mixin/AbstractArrowMixin.java index 00086ff6..3ca94b96 100644 --- a/src/main/java/com/bibireden/playerex/mixin/AbstractArrowMixin.java +++ b/src/main/java/com/bibireden/playerex/mixin/AbstractArrowMixin.java @@ -22,58 +22,43 @@ public abstract class AbstractArrowMixin extends Projectile { @Shadow public abstract void setCritArrow(boolean critical); - // Constructor for the mixin class + @Shadow public abstract boolean isCritArrow(); + private AbstractArrowMixin(EntityType entityType, Level level) { super(entityType, level); } - @SuppressWarnings("UnreachableCode") @Inject(method = "onHitEntity", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/projectile/AbstractArrow;isCritArrow()Z")) - private void playerex_onEntityHit(EntityHitResult entityHitResult, CallbackInfo info) { - AbstractArrow projectileEntity = (AbstractArrow) (Object) this; - Entity entity = projectileEntity.getOwner(); - - if (entity instanceof LivingEntity) { - - Optional rangedCritChanceOptional = DataAttributesAPI.getValue(PlayerEXAttributes.RANGED_CRITICAL_CHANCE, (LivingEntity) entity); - - if (rangedCritChanceOptional.isPresent()) { - projectileEntity.setCritArrow(false); - } - if (this.getOwner() instanceof LivingEntity owner) { - DataAttributesAPI.getValue(PlayerEXAttributes.RANGED_CRITICAL_CHANCE, owner).ifPresent((chance) -> this.setCritArrow(false)); - } + private void playerex$onEntityHit(EntityHitResult entityHitResult, CallbackInfo info) { + if (this.getOwner() instanceof LivingEntity entity) { + DataAttributesAPI.getValue(PlayerEXAttributes.RANGED_CRITICAL_CHANCE, entity).ifPresent((chance) -> + this.setCritArrow(false) + ); } } - @SuppressWarnings("UnreachableCode") @ModifyArg(method = "onHitEntity", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;hurt(Lnet/minecraft/world/damagesource/DamageSource;F)Z")) - private float playerex_onEntityHit(float i) { - AbstractArrow projectileEntity = (AbstractArrow)(Object) this; - Entity owner = projectileEntity.getOwner(); - double damage = i; + private float playerex$onEntityHit(float original) { + if (this.getOwner() instanceof LivingEntity entity) { + final float damage = original; - if(owner instanceof LivingEntity livingEntity) { - final double amount = damage; - - Optional rangedCritOptional = DataAttributesAPI.getValue(PlayerEXAttributes.RANGED_CRITICAL_CHANCE, livingEntity); - - if (rangedCritOptional.isPresent()) - { - boolean cache = livingEntity.getRandom().nextFloat() < rangedCritOptional.get(); - projectileEntity.setCritArrow(cache); - - if (cache) - { - Optional rangedCritDamageOptional = DataAttributesAPI.getValue(PlayerEXAttributes.RANGED_CRITICAL_DAMAGE, livingEntity); - if (rangedCritOptional.isPresent()) - { - damage = amount * (1.0 + (10.0 * rangedCritDamageOptional.get())); - } + boolean isCritical = DataAttributesAPI.getValue(PlayerEXAttributes.RANGED_CRITICAL_CHANCE, entity) + .map((chance) -> { + boolean shouldCritical = entity.getRandom().nextFloat() < chance; + this.setCritArrow(shouldCritical); + return shouldCritical; } + ).orElse(this.isCritArrow()); + + if (isCritical) { + return DataAttributesAPI.getValue(PlayerEXAttributes.RANGED_CRITICAL_DAMAGE, entity) + .map((v) -> (float) (damage * (1.0 + (10.0 * v)))) + .orElseGet(() -> { + final long offset = this.random.nextInt(Math.round(original) / 2 + 2); + return Math.min(offset + original, Integer.MAX_VALUE); + }); } } - - return (float) damage; + return original; } } diff --git a/src/main/java/com/bibireden/playerex/mixin/ExperienceOrbMixin.java b/src/main/java/com/bibireden/playerex/mixin/ExperienceOrbMixin.java index 0ad1b1e9..896e8513 100644 --- a/src/main/java/com/bibireden/playerex/mixin/ExperienceOrbMixin.java +++ b/src/main/java/com/bibireden/playerex/mixin/ExperienceOrbMixin.java @@ -3,6 +3,7 @@ import com.bibireden.playerex.components.PlayerEXComponents; import net.minecraft.core.BlockPos; import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.ExperienceOrb; import net.minecraft.world.level.Level; import net.minecraft.world.level.chunk.ChunkAccess; @@ -12,14 +13,16 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(ExperienceOrb.class) -public abstract class ExperienceOrbMixin { +public abstract class ExperienceOrbMixin extends Entity { + public ExperienceOrbMixin(EntityType entityType, Level level) { super(entityType, level); } + @Inject(method = "(Lnet/minecraft/world/level/Level;DDDI)V", at = @At("TAIL")) private void playerex$init(Level world, double x, double y, double z, int amount, CallbackInfo ci) { BlockPos pos = BlockPos.containing(x, y, z); ChunkAccess chunk = world.getChunk(pos); PlayerEXComponents.EXPERIENCE_DATA.maybeGet(chunk).ifPresent(data -> { if (data.updateExperienceNegationFactor(amount)) { - ((ExperienceOrb) (Object) this).remove(Entity.RemovalReason.DISCARDED); + this.remove(Entity.RemovalReason.DISCARDED); } }); } diff --git a/src/main/java/com/bibireden/playerex/mixin/InventoryMixin.java b/src/main/java/com/bibireden/playerex/mixin/InventoryMixin.java index 6e802bab..88db2758 100644 --- a/src/main/java/com/bibireden/playerex/mixin/InventoryMixin.java +++ b/src/main/java/com/bibireden/playerex/mixin/InventoryMixin.java @@ -18,7 +18,7 @@ public abstract class InventoryMixin { @ModifyReturnValue(method = "getDestroySpeed", at = @At("RETURN")) private float playerex$getBlockBreakingSpeed(float original) { - Optional maybeBreakingSpeed = DataAttributesAPI.INSTANCE.getValue(PlayerEXAttributes.BREAKING_SPEED, this.player); + Optional maybeBreakingSpeed = DataAttributesAPI.getValue(PlayerEXAttributes.BREAKING_SPEED, this.player); return maybeBreakingSpeed.map(v -> original + v.floatValue() - 1.0F).orElse(original); } } diff --git a/src/main/java/com/bibireden/playerex/mixin/LivingEntityMixin.java b/src/main/java/com/bibireden/playerex/mixin/LivingEntityMixin.java index cd5a99bd..d65c0e5f 100644 --- a/src/main/java/com/bibireden/playerex/mixin/LivingEntityMixin.java +++ b/src/main/java/com/bibireden/playerex/mixin/LivingEntityMixin.java @@ -27,9 +27,7 @@ public abstract class LivingEntityMixin { @Inject(method = "heal", at = @At("HEAD"), cancellable = true) private void playerex$heal(float original, CallbackInfo ci) { final boolean cancelled = LivingEntityEvents.SHOULD_HEAL.invoker().shouldHeal((LivingEntity) (Object) this, original); - if (!cancelled) { - ci.cancel(); - } + if (!cancelled) ci.cancel(); } @Inject(method = "tick", at = @At("TAIL")) diff --git a/src/main/java/com/bibireden/playerex/mixin/PlayerMixin.java b/src/main/java/com/bibireden/playerex/mixin/PlayerMixin.java index 12874428..01678415 100644 --- a/src/main/java/com/bibireden/playerex/mixin/PlayerMixin.java +++ b/src/main/java/com/bibireden/playerex/mixin/PlayerMixin.java @@ -9,7 +9,6 @@ @Mixin(Player.class) public abstract class PlayerMixin { - @ModifyVariable(method = "attack", at = @At("STORE"), name = "bl3", ordinal = 2) private boolean playerex_attack(boolean bl3, Entity target) { return PlayerEntityEvents.SHOULD_CRITICAL.invoker().shouldCritical((Player)(Object) this, target, bl3); diff --git a/src/main/java/com/bibireden/playerex/mixin/ServerLevelMixin.java b/src/main/java/com/bibireden/playerex/mixin/ServerLevelMixin.java deleted file mode 100644 index a4ac9874..00000000 --- a/src/main/java/com/bibireden/playerex/mixin/ServerLevelMixin.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.bibireden.playerex.mixin; - -import net.minecraft.server.level.ServerLevel; -import org.spongepowered.asm.mixin.Mixin; - -@Mixin(ServerLevel.class) -public abstract class ServerLevelMixin {} diff --git a/src/main/java/com/bibireden/playerex/mixin/ServerPlayerMixin.java b/src/main/java/com/bibireden/playerex/mixin/ServerPlayerMixin.java index 53de7062..eb4c7b5b 100644 --- a/src/main/java/com/bibireden/playerex/mixin/ServerPlayerMixin.java +++ b/src/main/java/com/bibireden/playerex/mixin/ServerPlayerMixin.java @@ -5,27 +5,30 @@ import com.bibireden.playerex.factory.ServerNetworkingFactory; import com.bibireden.playerex.networking.types.NotificationType; import com.bibireden.playerex.util.PlayerEXUtil; +import com.mojang.authlib.GameProfile; +import net.minecraft.core.BlockPos; import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.Level; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -@SuppressWarnings("UnreachableCode") @Mixin(ServerPlayer.class) -public abstract class ServerPlayerMixin { +public abstract class ServerPlayerMixin extends Player { + public ServerPlayerMixin(Level level, BlockPos pos, float yRot, GameProfile gameProfile) { + super(level, pos, yRot, gameProfile); + } + @Inject(method = "giveExperienceLevels", at = @At("TAIL")) private void addExperienceLevels(int levels, CallbackInfo ci) { - ServerPlayer player = (ServerPlayer) (Object) this; - PlayerDataComponent component = (PlayerDataComponent) PlayerEXComponents.PLAYER_DATA.get(player); - - int current = player.experienceLevel; - int required = PlayerEXUtil.getRequiredXpForNextLevel(player); + PlayerDataComponent component = (PlayerDataComponent) this.getComponent(PlayerEXComponents.PLAYER_DATA); - if (current >= required) { + if (this.experienceLevel >= PlayerEXUtil.getRequiredXpForNextLevel(this)) { if (!component.isLevelUpNotified()) { component.setLevelUpNotified(true); - ServerNetworkingFactory.notify(player, NotificationType.LevelUpAvailable); + ServerNetworkingFactory.notify(this, NotificationType.LevelUpAvailable); } } else { diff --git a/src/main/kotlin/com/bibireden/playerex/PlayerEX.kt b/src/main/kotlin/com/bibireden/playerex/PlayerEX.kt index b5c8aa47..7ec9b6e0 100644 --- a/src/main/kotlin/com/bibireden/playerex/PlayerEX.kt +++ b/src/main/kotlin/com/bibireden/playerex/PlayerEX.kt @@ -1,10 +1,15 @@ package com.bibireden.playerex +import com.bibireden.data_attributes.api.DataAttributesAPI import com.bibireden.data_attributes.api.attribute.EntityAttributeSupplier import com.bibireden.data_attributes.api.event.EntityAttributeModifiedEvents import com.bibireden.data_attributes.api.factory.DefaultAttributeFactory +import com.bibireden.opc.api.OfflinePlayerCacheAPI import com.bibireden.playerex.api.PlayerEXAPI +import com.bibireden.playerex.api.PlayerEXCachedKeys +import com.bibireden.playerex.api.PlayerEXCachedKeys.Level import com.bibireden.playerex.api.attribute.DefaultAttributeImpl +import com.bibireden.playerex.api.attribute.PlayerEXAttributes import com.bibireden.playerex.api.event.LivingEntityEvents import com.bibireden.playerex.api.event.PlayerEXSoundEvents import com.bibireden.playerex.api.event.PlayerEntityEvents @@ -17,6 +22,9 @@ import com.bibireden.playerex.networking.registerServerbound import com.bibireden.playerex.networking.types.UpdatePacketType import de.dafuqs.additionalentityattributes.AdditionalEntityAttributes import eu.pb4.placeholders.api.Placeholders +import io.wispforest.endec.Endec +import io.wispforest.endec.impl.BuiltInEndecs +import io.wispforest.endec.impl.RecordEndec import net.fabricmc.api.ModInitializer import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback import net.fabricmc.fabric.api.entity.event.v1.ServerPlayerEvents @@ -26,6 +34,7 @@ import net.minecraft.core.registries.BuiltInRegistries import net.minecraft.resources.ResourceLocation import net.minecraft.world.entity.ai.attributes.Attributes import org.slf4j.LoggerFactory +import kotlin.jvm.optionals.getOrElse object PlayerEX : ModInitializer { const val MOD_ID: String = "playerex" @@ -40,7 +49,7 @@ object PlayerEX : ModInitializer { private val gimmick = listOf( "Let's do it right this time...", - "PlayerEX: Bringing leveling and attribute manipulation to your doorstep." + "We test in production (not really).", ).random() override fun onInitialize() { @@ -99,4 +108,10 @@ object PlayerEX : ModInitializer { LOGGER.info(gimmick) } + + init { + OfflinePlayerCacheAPI.register(PlayerEXCachedKeys.LEVEL_KEY, Level::class.java, Level.CODEC) { + Level(DataAttributesAPI.getValue(PlayerEXAttributes.LEVEL, it).map(Double::toInt).orElse(0)) + } + } } \ No newline at end of file diff --git a/src/main/kotlin/com/bibireden/playerex/api/PlayerEXAPI.kt b/src/main/kotlin/com/bibireden/playerex/api/PlayerEXAPI.kt index 95ac1fdb..59ba3b88 100644 --- a/src/main/kotlin/com/bibireden/playerex/api/PlayerEXAPI.kt +++ b/src/main/kotlin/com/bibireden/playerex/api/PlayerEXAPI.kt @@ -15,6 +15,7 @@ object PlayerEXAPI { * @param function Using the incoming damage conditions, modifies the incoming * damage before it actually damages. */ + @JvmStatic fun registerDamageModification(predicate: DamagePredicate, function: DamageFunction) { DamageModificationRegistry.register(predicate, function) } @@ -26,25 +27,18 @@ object PlayerEXAPI { * * @param condition */ + @JvmStatic fun registerRefundCondition(condition: RefundCondition) { RefundConditionRegistry.register(condition) } -// /** -// * Registers an Attribute Menu. These are displayed in PlayerEX's attributes screen. -// * -// * @param screen -// */ -// fun registerAttributeMenu(menu: AttributesMenu) { -// AttributesMenuRegistry.register(menu) -// } - /** * @return Returns all the registered refund conditions. Note that while this is * mutable and backed by the original registry, * you should avoid modification and treat as read-only! * @since 3.5.0 */ + @JvmStatic val refundConditions: List get() = RefundConditionRegistry.get() } \ No newline at end of file diff --git a/src/main/kotlin/com/bibireden/playerex/api/PlayerEXCachedKeys.kt b/src/main/kotlin/com/bibireden/playerex/api/PlayerEXCachedKeys.kt index f83b94b7..0beda48e 100644 --- a/src/main/kotlin/com/bibireden/playerex/api/PlayerEXCachedKeys.kt +++ b/src/main/kotlin/com/bibireden/playerex/api/PlayerEXCachedKeys.kt @@ -1,9 +1,19 @@ package com.bibireden.playerex.api -import com.bibireden.opc.api.OfflinePlayerCacheAPI -import com.bibireden.playerex.keys.LevelKey +import com.mojang.serialization.Codec +import com.mojang.serialization.codecs.RecordCodecBuilder +import net.minecraft.resources.ResourceLocation object PlayerEXCachedKeys { + @JvmRecord + data class Level(val level: Int) { + companion object { + val CODEC = RecordCodecBuilder.create { + it.group(Codec.INT.fieldOf("level").forGetter(Level::level)).apply(it, ::Level) + } + } + } + @JvmField - val LEVEL_KEY = OfflinePlayerCacheAPI.register(LevelKey()) + val LEVEL_KEY = ResourceLocation.tryBuild("playerex", "level")!! } \ No newline at end of file diff --git a/src/main/kotlin/com/bibireden/playerex/api/PlayerEXModifiers.kt b/src/main/kotlin/com/bibireden/playerex/api/PlayerEXModifiers.kt index d9a03bba..3d2f8b1d 100644 --- a/src/main/kotlin/com/bibireden/playerex/api/PlayerEXModifiers.kt +++ b/src/main/kotlin/com/bibireden/playerex/api/PlayerEXModifiers.kt @@ -3,5 +3,6 @@ package com.bibireden.playerex.api import java.util.UUID object PlayerEXModifiers { + @JvmField val UUID: UUID = java.util.UUID.fromString("0f320cdd-8b2e-47a6-917e-adca8f899495") } \ No newline at end of file diff --git a/src/main/kotlin/com/bibireden/playerex/api/attribute/DefaultAttributeImpl.kt b/src/main/kotlin/com/bibireden/playerex/api/attribute/DefaultAttributeImpl.kt index 032df745..b4d8023c 100644 --- a/src/main/kotlin/com/bibireden/playerex/api/attribute/DefaultAttributeImpl.kt +++ b/src/main/kotlin/com/bibireden/playerex/api/attribute/DefaultAttributeImpl.kt @@ -11,7 +11,9 @@ import de.dafuqs.additionalentityattributes.AdditionalEntityAttributes import net.fabric_extras.ranged_weapon.api.EntityAttributes_RangedWeapon import net.minecraft.resources.ResourceLocation import net.minecraft.world.entity.ai.attributes.Attributes +import org.jetbrains.annotations.ApiStatus +@ApiStatus.Internal object DefaultAttributeImpl { val OVERRIDES: Map = mutableMapOf( PlayerEXAttributes.POISON_RESISTANCE.id to AttributeOverride( 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 16bb9c54..78ecd556 100644 --- a/src/main/kotlin/com/bibireden/playerex/api/attribute/PlayerEXAttributes.kt +++ b/src/main/kotlin/com/bibireden/playerex/api/attribute/PlayerEXAttributes.kt @@ -75,7 +75,8 @@ object PlayerEXAttributes { val attribute = RangedAttribute("attribute.name.${PlayerEX.MOD_ID}.$path", base, min, max) return Registry.register(BuiltInRegistries.ATTRIBUTE, ResourceLocation.tryBuild(PlayerEX.MOD_ID, path)!!, attribute) } - + + @JvmField val PRIMARY_ATTRIBUTE_IDS: Set = setOf( CONSTITUTION.id, STRENGTH.id, diff --git a/src/main/kotlin/com/bibireden/playerex/api/event/PlayerEXSoundEvents.kt b/src/main/kotlin/com/bibireden/playerex/api/event/PlayerEXSoundEvents.kt index 9338fecf..5974c3ad 100644 --- a/src/main/kotlin/com/bibireden/playerex/api/event/PlayerEXSoundEvents.kt +++ b/src/main/kotlin/com/bibireden/playerex/api/event/PlayerEXSoundEvents.kt @@ -4,7 +4,10 @@ import com.bibireden.playerex.PlayerEX import net.minecraft.sounds.SoundEvent object PlayerEXSoundEvents { + @JvmField val LEVEL_UP_SOUND = SoundEvent.createVariableRangeEvent(PlayerEX.id("level_up")) + @JvmField val SPEND_SOUND = SoundEvent.createVariableRangeEvent(PlayerEX.id("spend")) + @JvmField val REFUND_SOUND = SoundEvent.createVariableRangeEvent(PlayerEX.id("refund")) } \ No newline at end of file diff --git a/src/main/kotlin/com/bibireden/playerex/api/event/PlayerEntityEvents.kt b/src/main/kotlin/com/bibireden/playerex/api/event/PlayerEntityEvents.kt index 068bde7b..06784b17 100644 --- a/src/main/kotlin/com/bibireden/playerex/api/event/PlayerEntityEvents.kt +++ b/src/main/kotlin/com/bibireden/playerex/api/event/PlayerEntityEvents.kt @@ -8,7 +8,6 @@ import net.minecraft.world.entity.Entity import net.minecraft.world.entity.player.Player object PlayerEntityEvents { - /** * Fired if the player lands a critical hit. The result is the damage. */ diff --git a/src/main/kotlin/com/bibireden/playerex/compat/CompatUtils.kt b/src/main/kotlin/com/bibireden/playerex/compat/CompatUtils.kt index fe44fec9..70636681 100644 --- a/src/main/kotlin/com/bibireden/playerex/compat/CompatUtils.kt +++ b/src/main/kotlin/com/bibireden/playerex/compat/CompatUtils.kt @@ -1,7 +1,9 @@ package com.bibireden.playerex.compat import net.fabricmc.loader.api.FabricLoader +import org.jetbrains.annotations.ApiStatus +@ApiStatus.Internal object CompatUtils { fun isModLoaded(id: String): Boolean = FabricLoader.getInstance().isModLoaded(id) } \ No newline at end of file diff --git a/src/main/kotlin/com/bibireden/playerex/factory/PlaceholderFactory.kt b/src/main/kotlin/com/bibireden/playerex/factory/PlaceholderFactory.kt index d5ac14f6..d73c3502 100644 --- a/src/main/kotlin/com/bibireden/playerex/factory/PlaceholderFactory.kt +++ b/src/main/kotlin/com/bibireden/playerex/factory/PlaceholderFactory.kt @@ -1,10 +1,8 @@ package com.bibireden.playerex.factory -import com.bibireden.data_attributes.api.DataAttributesAPI -import com.bibireden.opc.cache.OfflinePlayerCache +import com.bibireden.opc.api.OfflinePlayerCacheAPI import com.bibireden.playerex.PlayerEX import com.bibireden.playerex.api.PlayerEXCachedKeys -import com.bibireden.playerex.api.attribute.PlayerEXAttributes import com.bibireden.playerex.ext.level import eu.pb4.placeholders.api.PlaceholderHandler import eu.pb4.placeholders.api.PlaceholderResult @@ -19,39 +17,35 @@ object PlaceholderFactory { private fun nameLevelPair(server: MinecraftServer, namesIn: Collection, indexIn: Int): Pair { - val cache = OfflinePlayerCache.get(server) + val cache = OfflinePlayerCacheAPI.getCache(server) - if (cache !== null) { - val names: ArrayList> = ArrayList(namesIn.size); + val names: ArrayList> = ArrayList(namesIn.size); - var i = 0 + var i = 0 - for (name: String in namesIn) { - val cachedData = cache.get(server, name, PlayerEXCachedKeys.LEVEL_KEY) ?: continue - - names[i] = Pair(name, cachedData) + for (name: String in namesIn) { + cache.getEntry(PlayerEXCachedKeys.Level::class.java, name).ifPresent { + names[i] = Pair(name, it.level) i++ } + } - names.sortWith(Comparator.comparing { (_, level) -> level }) - - val j = Mth.clamp(indexIn, 1, names.size) + names.sortWith(Comparator.comparing { (_, level) -> level }) - return names[names.size - j] - } + val j = Mth.clamp(indexIn, 1, names.size) - return Pair("", 0) + return names[names.size - j] } private fun top(stringFunction: (Pair) -> String): PlaceholderHandler { return PlaceholderHandler { ctx, arg -> val server = ctx.server() - val cache = OfflinePlayerCache.get(server) ?: return@PlaceholderHandler PlaceholderResult.invalid("Improper cache") + val cache = OfflinePlayerCacheAPI.getCache(server) var index: Int = 1 - val names: Collection = cache.usernames(server) + val names: Collection = cache.usernames if (arg !== null) { diff --git a/src/main/kotlin/com/bibireden/playerex/keys/LevelKey.kt b/src/main/kotlin/com/bibireden/playerex/keys/LevelKey.kt deleted file mode 100644 index 8e97d91c..00000000 --- a/src/main/kotlin/com/bibireden/playerex/keys/LevelKey.kt +++ /dev/null @@ -1,22 +0,0 @@ -package com.bibireden.playerex.keys - -import com.bibireden.data_attributes.api.DataAttributesAPI -import com.bibireden.opc.api.CachedPlayerKey -import com.bibireden.playerex.PlayerEX -import com.bibireden.playerex.api.attribute.PlayerEXAttributes -import net.minecraft.nbt.CompoundTag -import net.minecraft.server.level.ServerPlayer - -class LevelKey : CachedPlayerKey(PlayerEX.id("level")) { - override fun get(player: ServerPlayer): Int { - return DataAttributesAPI.getValue(PlayerEXAttributes.LEVEL, player).map(Double::toInt).orElse(0) - } - - override fun readFromNbt(tag: CompoundTag): Int { - return tag.getInt("level") - } - - override fun writeToNbt(tag: CompoundTag, value: Any) { - if (value is Int) tag.putInt("level", value) - } -} \ No newline at end of file diff --git a/src/main/kotlin/com/bibireden/playerex/networking/NetworkingChannels.kt b/src/main/kotlin/com/bibireden/playerex/networking/NetworkingChannels.kt index 60c98da9..52024c1e 100644 --- a/src/main/kotlin/com/bibireden/playerex/networking/NetworkingChannels.kt +++ b/src/main/kotlin/com/bibireden/playerex/networking/NetworkingChannels.kt @@ -15,6 +15,8 @@ fun OwoNetChannel.registerClientbound(clazz: KClass, handler: Ow } object NetworkingChannels { + @JvmField val MODIFY = OwoNetChannel.create(PlayerEX.id("modify")) + @JvmField val NOTIFICATIONS = OwoNetChannel.create(PlayerEX.id("notifications")) } \ No newline at end of file diff --git a/src/main/kotlin/com/bibireden/playerex/registry/DamageModificationRegistry.kt b/src/main/kotlin/com/bibireden/playerex/registry/DamageModificationRegistry.kt index 32f45a75..78c4bde7 100644 --- a/src/main/kotlin/com/bibireden/playerex/registry/DamageModificationRegistry.kt +++ b/src/main/kotlin/com/bibireden/playerex/registry/DamageModificationRegistry.kt @@ -6,10 +6,12 @@ import com.bibireden.playerex.api.damage.DamagePredicate object DamageModificationRegistry { private val entries: MutableList = mutableListOf() + @JvmStatic fun register(predicate: DamagePredicate, function: DamageFunction) { entries.add { it(predicate, function) } } + @JvmStatic fun get() = entries.toList() fun interface DamageModification { diff --git a/src/main/kotlin/com/bibireden/playerex/util/PlayerEXUtil.kt b/src/main/kotlin/com/bibireden/playerex/util/PlayerEXUtil.kt index 039d7675..879c9204 100644 --- a/src/main/kotlin/com/bibireden/playerex/util/PlayerEXUtil.kt +++ b/src/main/kotlin/com/bibireden/playerex/util/PlayerEXUtil.kt @@ -24,6 +24,7 @@ object PlayerEXUtil { private val expression: Expression get() = createExpression() + @JvmStatic private fun createExpression(): Expression { return ExpressionBuilder(PlayerEX.CONFIG.levelFormula).variable(VARIABLE).function(STAIRCASE_FUNCTION).build() } diff --git a/src/main/resources/playerex.mixins.json b/src/main/resources/playerex.mixins.json index c1a9805d..4aac6900 100644 --- a/src/main/resources/playerex.mixins.json +++ b/src/main/resources/playerex.mixins.json @@ -8,7 +8,6 @@ "InventoryMixin", "LivingEntityMixin", "PlayerMixin", - "ServerLevelMixin", "ServerPlayerMixin" ], "injectors": { From 7617c91444fd3772855ff71a089f1a2db324ae79 Mon Sep 17 00:00:00 2001 From: Bibi Reden Date: Fri, 2 Aug 2024 02:19:52 -0500 Subject: [PATCH 04/11] trim CI to get mcver --- .github/workflows/build-and-deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-and-deploy.yml b/.github/workflows/build-and-deploy.yml index bb61f224..2fc43aec 100644 --- a/.github/workflows/build-and-deploy.yml +++ b/.github/workflows/build-and-deploy.yml @@ -52,7 +52,7 @@ jobs: if: github.ref == 'refs/heads/${{ env.BRANCH_PREFIX }}' id: minecraft_version run: | - minecraft_version_val=$(grep "mod_version" gradle.properties | cut -d'=' -f2 | cut -d'-' -f1 | tr -d '\n') + minecraft_version_val=$(grep "mod_version" gradle.properties | cut -d'+' -f2 | cut -d'-' -f1 | tr -d '\n') echo "minecraft_version=$minecraft_version_val" >> $GITHUB_OUTPUT - name: deploy with mc-publish if: github.ref == 'refs/heads/${{ env.BRANCH_PREFIX }}' From 137d5dc108fdd42cf2ef008bb4fc294626e48a83 Mon Sep 17 00:00:00 2001 From: Bibi Reden Date: Fri, 2 Aug 2024 02:21:05 -0500 Subject: [PATCH 05/11] Move to latest OPC --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 6cabbfe7..754e909e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -30,7 +30,7 @@ placeholder_api_version=2.1.1+1.20 ranged_weapon_api_version=1.1.2+1.20.1 # in-house -opc_version=2.0.0+1.20.1-beta.1-fabric +opc_version=2.0.0+1.20.1-beta.2-fabric data_attributes_version=2.0.0-beta.7+1.20.1-fabric # owo From 907bfcc938bcfd955fd9c54b00f810cc10f0d1ae Mon Sep 17 00:00:00 2001 From: Bibi Reden Date: Fri, 2 Aug 2024 02:56:15 -0500 Subject: [PATCH 06/11] Step alpha 9 to resolve issue with OPC --- CHANGELOG.md | 4 +--- gradle.properties | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6e1aa040..ea43764e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,2 @@ ## Changes ⚒️ -- Updated to a newer build of `OfflinePlayerCache`. -- Changed some more internals. -- Reimplemented original calculation of projectile critical chance. \ No newline at end of file +- Resolved issues with OPC. \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 754e909e..bb219371 100644 --- a/gradle.properties +++ b/gradle.properties @@ -17,7 +17,7 @@ parchment_version=1.20.1:2023.09.03 quilt_mappings_version=23 # Mod Properties -mod_version=4.0.0+1.20.1-alpha.8 +mod_version=4.0.0+1.20.1-alpha.9 maven_group=com.bibireden.playerex archives_base_name=playerex-directors-cut From d239919b8acc753fc7f42ffbea62a4cf52190324 Mon Sep 17 00:00:00 2001 From: Bibi Reden Date: Sun, 4 Aug 2024 00:25:50 -0500 Subject: [PATCH 07/11] alpha.10 (resolve refund & mixinextras) (#20) * Fix issue with FOCUS not being recognized in refunds. * CL & alpha.10 staging --- .github/workflows/build-and-deploy.yml | 4 +++- CHANGELOG.md | 5 +++-- build.gradle | 2 ++ gradle.properties | 6 ++++-- .../kotlin/com/bibireden/playerex/factory/RefundFactory.kt | 1 + 5 files changed, 13 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build-and-deploy.yml b/.github/workflows/build-and-deploy.yml index 2fc43aec..47505dc2 100644 --- a/.github/workflows/build-and-deploy.yml +++ b/.github/workflows/build-and-deploy.yml @@ -1,12 +1,14 @@ -name: Build and Deploy +name: Deployment (J17) on: push: branches-ignore: - master + - "**/dev**" - "**-dev" - "**-dev**" - dev + jobs: build-and-deploy: env: diff --git a/CHANGELOG.md b/CHANGELOG.md index ea43764e..f22d84ba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,2 +1,3 @@ -## Changes ⚒️ -- Resolved issues with OPC. \ No newline at end of file +## Changes 🌽 +- Fixed issue with the new attribute **Focus** not being recognized in `RefundFactory`. +- Updated mixinextras directly in the mod to 0.4.0. \ No newline at end of file diff --git a/build.gradle b/build.gradle index 9a24f981..57cf8252 100644 --- a/build.gradle +++ b/build.gradle @@ -98,6 +98,8 @@ dependencies { modImplementation include("eu.pb4:placeholder-api:${project.placeholder_api_version}") implementation include("net.objecthunter:exp4j:${project.exp4j_version}") + + include(implementation(annotationProcessor("io.github.llamalad7:mixinextras-fabric:${project.mixinextras_version}"))) } processResources { diff --git a/gradle.properties b/gradle.properties index bb219371..3222f817 100644 --- a/gradle.properties +++ b/gradle.properties @@ -17,7 +17,7 @@ parchment_version=1.20.1:2023.09.03 quilt_mappings_version=23 # Mod Properties -mod_version=4.0.0+1.20.1-alpha.9 +mod_version=4.0.0+1.20.1-alpha.10 maven_group=com.bibireden.playerex archives_base_name=playerex-directors-cut @@ -31,7 +31,7 @@ ranged_weapon_api_version=1.1.2+1.20.1 # in-house opc_version=2.0.0+1.20.1-beta.2-fabric -data_attributes_version=2.0.0-beta.7+1.20.1-fabric +data_attributes_version=2.0.0-beta.8+1.20.1-fabric # owo owo_version=0.11.2+1.20 @@ -42,3 +42,5 @@ endec_gson_version=0.1.4 endec_netty_version=0.1.3 exp4j_version=0.4.8 + +mixinextras_version=0.4.0 diff --git a/src/main/kotlin/com/bibireden/playerex/factory/RefundFactory.kt b/src/main/kotlin/com/bibireden/playerex/factory/RefundFactory.kt index 24bb810c..6b4331e7 100644 --- a/src/main/kotlin/com/bibireden/playerex/factory/RefundFactory.kt +++ b/src/main/kotlin/com/bibireden/playerex/factory/RefundFactory.kt @@ -12,5 +12,6 @@ object RefundFactory { registry.accept { data, player -> data.get(PlayerEXAttributes.DEXTERITY) } registry.accept { data, player -> data.get(PlayerEXAttributes.INTELLIGENCE) } registry.accept { data, player -> data.get(PlayerEXAttributes.LUCKINESS) } + registry.accept { data, player -> data.get(PlayerEXAttributes.FOCUS) } } } \ No newline at end of file From afd66d0ede6103fb26ed8092e966fa5900afc7ca Mon Sep 17 00:00:00 2001 From: Bibi Reden Date: Sun, 4 Aug 2024 20:54:22 -0500 Subject: [PATCH 08/11] Update sorting to function when adding other components --- CHANGELOG.md | 5 +++-- gradle.properties | 2 +- .../registry/PlayerEXMenuRegistry.java | 21 +++++++------------ .../playerex/ui/components/MenuComponent.kt | 2 +- .../ui/menus/PlayerEXAttributesMenu.kt | 2 +- 5 files changed, 13 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f22d84ba..0b6e2494 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,4 @@ ## Changes 🌽 -- Fixed issue with the new attribute **Focus** not being recognized in `RefundFactory`. -- Updated mixinextras directly in the mod to 0.4.0. \ No newline at end of file +- Fixed out-of-bounds exception when registering a menu. +- Renamed `rootComponent` in `MenuComponent` -> `screenRoot` to refer to the actual screens root. + - If you plan on using this component, know that you can access the functions/members you need directly from the object itself. \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 3222f817..ec0ee8b7 100644 --- a/gradle.properties +++ b/gradle.properties @@ -17,7 +17,7 @@ parchment_version=1.20.1:2023.09.03 quilt_mappings_version=23 # Mod Properties -mod_version=4.0.0+1.20.1-alpha.10 +mod_version=4.0.0+1.20.1-alpha.11 maven_group=com.bibireden.playerex archives_base_name=playerex-directors-cut diff --git a/src/client/java/com/bibireden/playerex/registry/PlayerEXMenuRegistry.java b/src/client/java/com/bibireden/playerex/registry/PlayerEXMenuRegistry.java index ac0f7202..2488195b 100644 --- a/src/client/java/com/bibireden/playerex/registry/PlayerEXMenuRegistry.java +++ b/src/client/java/com/bibireden/playerex/registry/PlayerEXMenuRegistry.java @@ -19,7 +19,7 @@ */ public final class PlayerEXMenuRegistry { @NotNull - private static final List>> ENTRIES = new ArrayList<>(); + private static final ArrayList>> ENTRIES = new ArrayList<>(); @NotNull private static final HashMap PRIORITY_ORDER = new HashMap<>(); @@ -29,19 +29,12 @@ public final class PlayerEXMenuRegistry { * which will be applied to the {@link PlayerEXScreen} as a page. */ public static void register(ResourceLocation id, @NotNull Class menu) { - Integer position = PRIORITY_ORDER.get(id.getNamespace()); - if (position != null) { - for (int i = 0; i < ENTRIES.size(); i++) { - ResourceLocation entryId = ENTRIES.get(i).getFirst(); - if (PRIORITY_ORDER.get(entryId.getNamespace()) >= position) { - position = i + 1; - } - } - ENTRIES.add(position, new Pair<>(id, menu)); - } - else { - ENTRIES.add(new Pair<>(id, menu)); - } + ENTRIES.add(new Pair<>(id, menu)); + ENTRIES.sort((a, b) -> { + var order = PRIORITY_ORDER.getOrDefault(a.getFirst().getNamespace(), Integer.MAX_VALUE); + var order2 = PRIORITY_ORDER.getOrDefault(b.getFirst().getNamespace(), Integer.MAX_VALUE); + return order.compareTo(order2); + }); } @NotNull diff --git a/src/client/kotlin/com/bibireden/playerex/ui/components/MenuComponent.kt b/src/client/kotlin/com/bibireden/playerex/ui/components/MenuComponent.kt index eaa3aefe..70164d12 100644 --- a/src/client/kotlin/com/bibireden/playerex/ui/components/MenuComponent.kt +++ b/src/client/kotlin/com/bibireden/playerex/ui/components/MenuComponent.kt @@ -36,7 +36,7 @@ abstract class MenuComponent(horizontalSizing: Sizing = Sizing.fill(100), vertic } /** Where ui-based logic should occur at, built off of the root of the screen's provided content area. */ - abstract fun build(rootComponent: FlowLayout) + abstract fun build(screenRoot: FlowLayout) fun interface OnLevelUpdated { fun onLevelUpdated(level: Int) diff --git a/src/client/kotlin/com/bibireden/playerex/ui/menus/PlayerEXAttributesMenu.kt b/src/client/kotlin/com/bibireden/playerex/ui/menus/PlayerEXAttributesMenu.kt index c57a14ac..313c5ba0 100644 --- a/src/client/kotlin/com/bibireden/playerex/ui/menus/PlayerEXAttributesMenu.kt +++ b/src/client/kotlin/com/bibireden/playerex/ui/menus/PlayerEXAttributesMenu.kt @@ -96,7 +96,7 @@ class PlayerEXAttributesMenu : MenuComponent(algorithm = Algorithm.HORIZONTAL) { } - override fun build(rootComponent: FlowLayout) { + override fun build(screenRoot: FlowLayout) { val player = client?.player ?: return val component = playerComponent ?: return From 6cc5df1855f96999b1d24b61972330c6bf6d0b68 Mon Sep 17 00:00:00 2001 From: Bibi Reden Date: Tue, 6 Aug 2024 18:26:27 -0500 Subject: [PATCH 09/11] HOTFIX FOR NEWER DATA ATTRIBUTES --- CHANGELOG.md | 6 +++--- gradle.properties | 6 +++--- .../playerex/components/player/PlayerDataComponent.kt | 2 +- .../com/bibireden/playerex/factory/PlaceholderFactory.kt | 4 +++- src/main/resources/fabric.mod.json | 4 ++-- 5 files changed, 12 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b6e2494..ddeea88b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ ## Changes 🌽 -- Fixed out-of-bounds exception when registering a menu. -- Renamed `rootComponent` in `MenuComponent` -> `screenRoot` to refer to the actual screens root. - - If you plan on using this component, know that you can access the functions/members you need directly from the object itself. \ No newline at end of file +- Uses the latest DataAttributes (beta.9) & OfflinePlayerCache. + - The namespace of DataAttributes got changed on this update, breaking the ability to use the mod with the latest one. This has been addressed now. +- This patches an issue when updating modifiers (for I forgot to update PlayerEX when changing namespaces.) \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index ec0ee8b7..894d140f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -17,7 +17,7 @@ parchment_version=1.20.1:2023.09.03 quilt_mappings_version=23 # Mod Properties -mod_version=4.0.0+1.20.1-alpha.11 +mod_version=4.0.0+1.20.1-alpha.12 maven_group=com.bibireden.playerex archives_base_name=playerex-directors-cut @@ -30,8 +30,8 @@ placeholder_api_version=2.1.1+1.20 ranged_weapon_api_version=1.1.2+1.20.1 # in-house -opc_version=2.0.0+1.20.1-beta.2-fabric -data_attributes_version=2.0.0-beta.8+1.20.1-fabric +opc_version=2.0.0+1.20.1-beta.4-fabric +data_attributes_version=2.0.0+1.20.1-beta.9-fabric # owo owo_version=0.11.2+1.20 diff --git a/src/main/kotlin/com/bibireden/playerex/components/player/PlayerDataComponent.kt b/src/main/kotlin/com/bibireden/playerex/components/player/PlayerDataComponent.kt index 62c02de9..bcad87c6 100644 --- a/src/main/kotlin/com/bibireden/playerex/components/player/PlayerDataComponent.kt +++ b/src/main/kotlin/com/bibireden/playerex/components/player/PlayerDataComponent.kt @@ -81,7 +81,7 @@ class PlayerDataComponent( private fun trySet(key: ResourceLocation, value: Double): Boolean { val (instance, isPlayerEXModifierPresent) = this.getInstance(key) ?: return false if (isPlayerEXModifierPresent) { - (instance as IEntityAttributeInstance).updateModifier(PlayerEXModifiers.UUID, value) + instance.`data_attributes$updateModifier`(PlayerEXModifiers.UUID, value) } else { instance.addPermanentModifier(AttributeModifier(PlayerEXModifiers.UUID, "PlayerEX Attribute", value, AttributeModifier.Operation.ADDITION)) diff --git a/src/main/kotlin/com/bibireden/playerex/factory/PlaceholderFactory.kt b/src/main/kotlin/com/bibireden/playerex/factory/PlaceholderFactory.kt index d73c3502..3b5a66e2 100644 --- a/src/main/kotlin/com/bibireden/playerex/factory/PlaceholderFactory.kt +++ b/src/main/kotlin/com/bibireden/playerex/factory/PlaceholderFactory.kt @@ -1,8 +1,10 @@ package com.bibireden.playerex.factory import com.bibireden.opc.api.OfflinePlayerCacheAPI +import com.bibireden.opc.api.ext.getEntry import com.bibireden.playerex.PlayerEX import com.bibireden.playerex.api.PlayerEXCachedKeys +import com.bibireden.playerex.api.PlayerEXCachedKeys.Level import com.bibireden.playerex.ext.level import eu.pb4.placeholders.api.PlaceholderHandler import eu.pb4.placeholders.api.PlaceholderResult @@ -24,7 +26,7 @@ object PlaceholderFactory { var i = 0 for (name: String in namesIn) { - cache.getEntry(PlayerEXCachedKeys.Level::class.java, name).ifPresent { + cache.getEntry(name).ifPresent { names[i] = Pair(name, it.level) i++ } diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index d6054164..31f768b4 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -45,7 +45,7 @@ "java": ">=17", "fabric-api": "*", "fabric-language-kotlin": ">=1.10.19+kotlin.1.9.23", - "data_attributes": ">=2.0.0-beta.7+1.20.1-fabric", + "data_attributes": ">=2.0.0+1.20.1-beta.9-fabric", "ranged_weapon_api": ">=1.1.0+1.20.1" }, "custom": { @@ -60,7 +60,7 @@ "dependencies": [ "fabric-api@>=0.92.2+1.20.1(required){modrinth:P7dR8mSH}{curseforge:306612}#(ignore:github)", "fabric-language-kotlin@>=1.9.5+kotlin.1.8.22(required){modrinth:Ha28R6CL}{curseforge:308769}#(ignore:github)", - "data-attributes-directors-cut@>=2.0.0-beta.7+1.20.1-fabric(required){modrinth:KCGxOJsE}{curseforge:955929}#(ignore:github)", + "data-attributes-directors-cut@>=2.0.0+1.20.1-beta.9-fabric(required){modrinth:KCGxOJsE}{curseforge:955929}#(ignore:github)", "owo-lib@0.11.2(required){modrinth:ccKDOlHs}{curseforge:532610}#(ignore:github)", "ranged_weapon_api@>=1.1.0+1.20.1(required){modrinth:AqaIIO6D}{curseforge:962162}#(ignore:github)", "cardinal-components@5.2.2(embedded){modrinth:K01OU20C}{curseforge:318449}#(ignore:github)", From bcccffc5b1e699ca074f8d6ae1d4f864d1faaaed Mon Sep 17 00:00:00 2001 From: Bibi Reden Date: Thu, 8 Aug 2024 00:00:15 -0500 Subject: [PATCH 10/11] Fix Fire Resistance (#21) * Update readme * Apply proper fire resistance * Stage update --- CHANGELOG.md | 5 +- README.md | 146 +++++++++++++----- gradle.properties | 4 +- .../playerex/mixin/InventoryMixin.java | 3 +- .../playerex/factory/DamageFactory.kt | 10 +- 5 files changed, 121 insertions(+), 47 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ddeea88b..94cb02cd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,3 @@ ## Changes 🌽 -- Uses the latest DataAttributes (beta.9) & OfflinePlayerCache. - - The namespace of DataAttributes got changed on this update, breaking the ability to use the mod with the latest one. This has been addressed now. -- This patches an issue when updating modifiers (for I forgot to update PlayerEX when changing namespaces.) \ No newline at end of file +- Update FLK +- Fixed **Fire Resistance** not calculating correctly. \ No newline at end of file diff --git a/README.md b/README.md index b6a74697..1e576ef1 100644 --- a/README.md +++ b/README.md @@ -1,36 +1,112 @@ ![logo](https://cdn.modrinth.com/data/cached_images/f8dd730cf295dc3a449337df81cc47e010eddf3e.png) -[![GitHub license](https://img.shields.io/badge/MIT-MIT?style=for-the-badge&label=LICENCE&labelColor=582b11&color=a48350&link=https%3A%2F%2Fgithub.com%2FPlayerEXDirectorsCut%2Fplayerex%2Fblob%2F1.20.1%2Fmain%2FLICENSE)](https://github.com/PlayerEXDirectorsCut/playerex/blob/1.20.1/main/LICENSE) -[![GitHub stars](https://img.shields.io/github/stars/PlayerEXDirectorsCut/playerex?style=for-the-badge&logo=github&color=ffb046&link=https%3A%2F%2Fgithub.com%2FPlayerEXDirectorsCut%2Fplayerex%2Fstargazers -)](https://github.com/PlayerEXDirectorsCut/playerex/stargazers) -[![GitHub forks](https://img.shields.io/github/forks/PlayerEXDirectorsCut/playerex?style=for-the-badge&logo=github&link=https%3A%2F%2Fgithub.com%2FPlayerEXDirectorsCut%2Fplayerex%2Fforks -)](https://github.com/PlayerEXDirectorsCut/playerex/forks) -[![GitHub issues](https://img.shields.io/github/issues/PlayerEXDirectorsCut/playerex?style=for-the-badge&logo=github&label=ISSUES&link=https%3A%2F%2Fgithub.com%2FPlayerEXDirectorsCut%2Fplayerex%2Fissues -)](https://github.com/PlayerEXDirectorsCut/playerex/issues) - -[![docs](https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/cozy/documentation/generic_vector.svg)](https://playerexdirectorscut.github.io/Bare-Minimum-Docs/) -![mkdocs](https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/cozy/built-with/mkdocs_vector.svg) -![java17](https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/cozy/built-with/java17_vector.svg) -[![curseforge](https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/cozy/available/curseforge_vector.svg)](https://www.curseforge.com/minecraft/mc-mods/playerex-directors-cut) -[![modrinth](https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/cozy/available/modrinth_vector.svg)](https://modrinth.com/mod/playerex-directors-cut) - -### Preamble - -PlayerEX: -Directors Cut is an entire rewrite of **[PlayerEx](https://www.curseforge.com/minecraft/mc-mods/playerex)** -(1.20.1+, though a ported version is available) and -a mod built using Fabric that adds RPG themed attributes to the game and the player. -It is available to download from [Curseforge](https://curseforge.com/minecraft/mc-mods/playerex-directors-cut) and [Modrinth](https://modrinth.com/mod/playerex-directors-cut). - -Find the original mod [here!](https://modrinth.com/mod/playerex) - -### Content - -In addition to attributes powered by [Data Attributes: Directors Cut](https://www.curseforge.com/minecraft/mc-mods/data-attributes-directors-cut), PlayerEX: Directors Cut adds a levelling system and skill points to spend, enabled through a nonintrusive vanilla-styled gui accessible from the inventory or by hotkey. For further documentation, as well as how to use the PlayerEX:Directors Cut API in your own project, please see the [wiki](https://github.com/CleverNucleus/PlayerEx/wiki). - -### Contributors (Former) - - [gyular](https://github.com/gyular) - Korean translation. - - [Hertz](https://github.com/elhertz) - Spanish translation. - - [MrTYZzik](https://github.com/MrTYZzik) - Russian translation. - - [Orygeunik](https://github.com/Orygeunik) - Russian translation improvements. - - [NianGuu](https://github.com/NianGuu) - Simplified Chinese - - [sky_bai](https://github.com/a1640727878) - Simplified Chinese (legacy release) + +

Forge when?

+ +
+ +

+ + + + +

+ +

+ fabric + quilt +

+ +

+ forge +

+

(though more assembly is required, see further below)

+ +

+ + + + + + + java + gradle + + + +

+ +
+ +_________________ + +
+ +![PlayerEX Screen at Level 5](https://cdn.modrinth.com/data/cached_images/a1932f9482b132e06b75717be8e060149b275b94.png) + +### Preamble 📝 + +PlayerEX is a fundamentally rewritten mod based on the work of **CleverNucleus's [PlayerEx](https://modrinth.com/mod/playerex)**. The mod provides RPG-themed attributes to the game and a configurable leveling system. + +### Content 📦 + +With higher-level, highly configurable attribute modification provided by **[Data Attributes: Directors Cut](https://www.curseforge.com/minecraft/mc-mods/data-attributes-directors-cut)**, PlayerEX integrates skill and refundable points to spend through the non-intrusive, extendable, and modern screen, which can be activated by a hotkey (default is `-`). + +### Extras 🎬 + +- **[EXHud](https://modrinth.com/mod/exhud-directors-cut)**, which provides an optional, opinionated and highly-configurable UI complimentary for PlayerEX, and has compatibility with other mods, such as [**Thermoo**](https://modrinth.com/mod/thermoo), and [**AppleSkin**](https://modrinth.com/mod/appleskin). + +- **[RelicEX](https://modrinth.com/mod/relicex-directors-cut)**, which adds relics, tomes, different ways to obtain level, skill, and refund points. + +- **[WizardEX](https://modrinth.com/mod/wizardex-directors-cut)**, which provides a layer between this mod and **[Wizards](https://modrinth.com/mod/wizards)** and other mods that use **[Spell Power Attributes](https://modrinth.com/mod/spell-power)**. + +### Wiki 📑 + +To learn more about the mod, you can go **[here!](https://bareminimumstudios.github.io/Bare-Minimum-Docs/)** + +### Developers 💻 + +Ah, my favorite people. You will get some more information on how to mod PlayerEX once the release is stable. For now, know that you will be getting: + +- A way to implement attribute modification (and target any attribute you want and apply functions to them) into a registry. +- Override **any** registered attribute. +- Apply **any** attribute to **any** `LivingEntity` (primarily for the player). +- Attach to a screen using `owo-lib`. +- And much more... + +### For Forge Users 🪨 + +Howdy, I know you have all been **dying** for a forge release. This will come in due time. For now, the mod has been rewritten for fabric, but due to its compatible and improved nature, there is a way you can play it! + +*Refer to the **Usage Guide** on [**Sinytra Connector**](https://modrinth.com/mod/connector) to get started.* + +> There is no guarantee that it will work for Forge completely, and support **can not** be provided until an actual release of a forge mod is created. + +### Contributors 🆘 + +### The People Who Made This A Reality + +- The studio +- The wispforest team 💖 +- One guy's modpack +- Literally **YOU** +- And most importantly, **CleverNucleus** + +### Translators (legacy, `<=3.*`) + +- [gyular](https://github.com/gyular) - Korean translation. +- [Hertz](https://github.com/elhertz) - Spanish translation. +- [MrTYZzik](https://github.com/MrTYZzik) - Russian translation. +- [Orygeunik](https://github.com/Orygeunik) - Russian translation improvements. +- [NianGuu](https://github.com/NianGuu) - Simplified Chinese +- [sky_bai](https://github.com/a1640727878) - Simplified Chinese (older releases) + +### A Thanks To Our Sponsor + +--- + +
+ +

Sponsor Banner

+

+ Use code "BAREMINIMUM" to get 15% off your first month! +

diff --git a/gradle.properties b/gradle.properties index 894d140f..ab546173 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,7 +9,7 @@ loader=fabric # Fabric Properties minecraft_version=1.20.1 loader_version=0.15.11 -fabric_kotlin_version=1.11.0+kotlin.2.0.0 +fabric_kotlin_version=1.12.0+kotlin.2.0.10 loom_version=1.7-SNAPSHOT # Mappings @@ -17,7 +17,7 @@ parchment_version=1.20.1:2023.09.03 quilt_mappings_version=23 # Mod Properties -mod_version=4.0.0+1.20.1-alpha.12 +mod_version=4.0.0+1.20.1-alpha.13 maven_group=com.bibireden.playerex archives_base_name=playerex-directors-cut diff --git a/src/main/java/com/bibireden/playerex/mixin/InventoryMixin.java b/src/main/java/com/bibireden/playerex/mixin/InventoryMixin.java index 88db2758..49bc5da1 100644 --- a/src/main/java/com/bibireden/playerex/mixin/InventoryMixin.java +++ b/src/main/java/com/bibireden/playerex/mixin/InventoryMixin.java @@ -18,7 +18,6 @@ public abstract class InventoryMixin { @ModifyReturnValue(method = "getDestroySpeed", at = @At("RETURN")) private float playerex$getBlockBreakingSpeed(float original) { - Optional maybeBreakingSpeed = DataAttributesAPI.getValue(PlayerEXAttributes.BREAKING_SPEED, this.player); - return maybeBreakingSpeed.map(v -> original + v.floatValue() - 1.0F).orElse(original); + return DataAttributesAPI.getValue(PlayerEXAttributes.BREAKING_SPEED, this.player).map((v) -> original + v.floatValue() - 1.0F).orElse(original); } } diff --git a/src/main/kotlin/com/bibireden/playerex/factory/DamageFactory.kt b/src/main/kotlin/com/bibireden/playerex/factory/DamageFactory.kt index bd072c9a..799d8ab0 100644 --- a/src/main/kotlin/com/bibireden/playerex/factory/DamageFactory.kt +++ b/src/main/kotlin/com/bibireden/playerex/factory/DamageFactory.kt @@ -13,24 +13,24 @@ object DamageFactory { fun forEach(registry: (damagePredicate: DamagePredicate, damageFunction: DamageFunction) -> Unit) { registry.invoke({ _, source, _ -> source.`is`(DamageTypes.ON_FIRE) }, { entity, _, damage -> - DataAttributesAPI.getValue(PlayerEXAttributes.FIRE_RESISTANCE, entity).map { ((1.0 - (it / 100)) * damage).toFloat() }.orElse(damage) + DataAttributesAPI.getValue(PlayerEXAttributes.FIRE_RESISTANCE, entity).map { damage * (1 - it) }.map(Double::toFloat).orElse(damage) }) registry.invoke({ _, source, _ -> source.`is`(DamageTypes.FREEZE)}, { living, _, damage -> - DataAttributesAPI.getValue(PlayerEXAttributes.FREEZE_RESISTANCE, living).map { (damage * (1.0 - it)).toFloat() }.orElse(damage) + DataAttributesAPI.getValue(PlayerEXAttributes.FREEZE_RESISTANCE, living).map { damage * (1 - it) }.map(Double::toFloat).orElse(damage) }) registry.invoke({ _, source, _ -> source.`is`(DamageTypes.LIGHTNING_BOLT)}, { living, _, damage -> - DataAttributesAPI.getValue(PlayerEXAttributes.LIGHTNING_RESISTANCE, living).map { (damage * (1.0 - it)).toFloat() }.orElse(damage) + DataAttributesAPI.getValue(PlayerEXAttributes.LIGHTNING_RESISTANCE, living).map { damage * (1 - it) }.map(Double::toFloat).orElse(damage) }) registry.invoke( { living, source, damage -> living.hasEffect(MobEffects.POISON) && source.`is`(DamageTypes.MAGIC) && damage <= 1.0F }, - {living, _, damage -> DataAttributesAPI.getValue(PlayerEXAttributes.POISON_RESISTANCE, living).map { (damage * (1.0 - it)).toFloat() }.orElse(damage) } + {living, _, damage -> DataAttributesAPI.getValue(PlayerEXAttributes.POISON_RESISTANCE, living).map { damage * (1 - it) }.map(Double::toFloat).orElse(damage) } ) registry.invoke({_, source, _ -> source.`is`(DamageTypes.WITHER) || (source.`is`(DamageTypes.INDIRECT_MAGIC) && ((source.directEntity is ThrownPotion) || (source.directEntity is AreaEffectCloud))) }, { living, source, damage -> DataAttributesAPI.getValue(PlayerEXAttributes.WITHER_RESISTANCE, living).map { if (source.`is`(DamageTypes.WITHER) && living.isInvertedHealAndHarm) return@map 0.0F if (source.`is`(DamageTypes.INDIRECT_MAGIC) && source.directEntity is ThrownPotion && living.isInvertedHealAndHarm) return@map damage - (damage * (1.0 - it)).toFloat() + (damage * 1 - it).toFloat() }.orElse(damage) }) } From b107804e34303d7ad2523a75456ffead018ee2e8 Mon Sep 17 00:00:00 2001 From: Bibi Reden Date: Fri, 9 Aug 2024 10:30:10 -0500 Subject: [PATCH 11/11] Force singleton init, fix patch, adjust for new DA --- CHANGELOG.md | 5 +- gradle.properties | 4 +- .../ui/components/AttributeComponent.kt | 2 +- .../kotlin/com/bibireden/playerex/PlayerEX.kt | 18 +- .../api/attribute/DefaultAttributeImpl.kt | 171 ------------------ .../bibireden/playerex/ext/EntityAttribute.kt | 8 +- .../data_attributes/entity_types/stock.json | 34 ++++ .../data_attributes/functions/stock.json | 146 +++++++++++++++ .../data_attributes/overrides/stock.json | 148 +++++++++++++++ 9 files changed, 348 insertions(+), 188 deletions(-) delete mode 100644 src/main/kotlin/com/bibireden/playerex/api/attribute/DefaultAttributeImpl.kt create mode 100644 src/main/resources/data/playerex/data_attributes/entity_types/stock.json create mode 100644 src/main/resources/data/playerex/data_attributes/functions/stock.json create mode 100644 src/main/resources/data/playerex/data_attributes/overrides/stock.json diff --git a/CHANGELOG.md b/CHANGELOG.md index 94cb02cd..e0855ec7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,4 @@ ## Changes 🌽 -- Update FLK -- Fixed **Fire Resistance** not calculating correctly. \ No newline at end of file +- Using the latest data-attributes with a supplied "stock" data-pack. +- You can clear your config if you wish to use stock, or keep your config with all the entries. +- Applied a patch for missing id's, which is an edge-case (will be labeled `unresolved:id`). \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index ab546173..2d8648de 100644 --- a/gradle.properties +++ b/gradle.properties @@ -17,7 +17,7 @@ parchment_version=1.20.1:2023.09.03 quilt_mappings_version=23 # Mod Properties -mod_version=4.0.0+1.20.1-alpha.13 +mod_version=4.0.0+1.20.1-alpha.14 maven_group=com.bibireden.playerex archives_base_name=playerex-directors-cut @@ -31,7 +31,7 @@ ranged_weapon_api_version=1.1.2+1.20.1 # in-house opc_version=2.0.0+1.20.1-beta.4-fabric -data_attributes_version=2.0.0+1.20.1-beta.9-fabric +data_attributes_version=2.0.0+1.20.1-beta.10-fabric # owo owo_version=0.11.2+1.20 diff --git a/src/client/kotlin/com/bibireden/playerex/ui/components/AttributeComponent.kt b/src/client/kotlin/com/bibireden/playerex/ui/components/AttributeComponent.kt index faaa5bcb..216ddc3a 100644 --- a/src/client/kotlin/com/bibireden/playerex/ui/components/AttributeComponent.kt +++ b/src/client/kotlin/com/bibireden/playerex/ui/components/AttributeComponent.kt @@ -28,7 +28,7 @@ class AttributeComponent(private val attribute: Attribute, private val player: P val label: AttributeLabelComponent fun refresh() { - val entries = DataAttributesAPI.clientManager.data.functions[attribute.id] + val entries = DataAttributesAPI.clientManager.functions[attribute.id] if (!entries.isNullOrEmpty()) { label.tooltip( Component.translatable("playerex.ui.main.modified_attributes").also { text -> diff --git a/src/main/kotlin/com/bibireden/playerex/PlayerEX.kt b/src/main/kotlin/com/bibireden/playerex/PlayerEX.kt index 7ec9b6e0..c6a8af51 100644 --- a/src/main/kotlin/com/bibireden/playerex/PlayerEX.kt +++ b/src/main/kotlin/com/bibireden/playerex/PlayerEX.kt @@ -3,13 +3,12 @@ package com.bibireden.playerex import com.bibireden.data_attributes.api.DataAttributesAPI import com.bibireden.data_attributes.api.attribute.EntityAttributeSupplier import com.bibireden.data_attributes.api.event.EntityAttributeModifiedEvents -import com.bibireden.data_attributes.api.factory.DefaultAttributeFactory import com.bibireden.opc.api.OfflinePlayerCacheAPI import com.bibireden.playerex.api.PlayerEXAPI import com.bibireden.playerex.api.PlayerEXCachedKeys import com.bibireden.playerex.api.PlayerEXCachedKeys.Level -import com.bibireden.playerex.api.attribute.DefaultAttributeImpl import com.bibireden.playerex.api.attribute.PlayerEXAttributes +import com.bibireden.playerex.api.attribute.TradeSkillAttributes import com.bibireden.playerex.api.event.LivingEntityEvents import com.bibireden.playerex.api.event.PlayerEXSoundEvents import com.bibireden.playerex.api.event.PlayerEntityEvents @@ -22,9 +21,6 @@ import com.bibireden.playerex.networking.registerServerbound import com.bibireden.playerex.networking.types.UpdatePacketType import de.dafuqs.additionalentityattributes.AdditionalEntityAttributes import eu.pb4.placeholders.api.Placeholders -import io.wispforest.endec.Endec -import io.wispforest.endec.impl.BuiltInEndecs -import io.wispforest.endec.impl.RecordEndec import net.fabricmc.api.ModInitializer import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback import net.fabricmc.fabric.api.entity.event.v1.ServerPlayerEvents @@ -33,18 +29,22 @@ import net.minecraft.core.Registry import net.minecraft.core.registries.BuiltInRegistries import net.minecraft.resources.ResourceLocation import net.minecraft.world.entity.ai.attributes.Attributes +import org.slf4j.Logger import org.slf4j.LoggerFactory -import kotlin.jvm.optionals.getOrElse object PlayerEX : ModInitializer { const val MOD_ID: String = "playerex" @JvmField - val LOGGER = LoggerFactory.getLogger(MOD_ID) + val LOGGER: Logger = LoggerFactory.getLogger(MOD_ID) @JvmField val CONFIG = PlayerEXConfig.createAndLoad() + // this is literally here to initialize the singletons... + val PRIMARY_ATTRIBUTE_IDS = PlayerEXAttributes.PRIMARY_ATTRIBUTE_IDS + val TRADE_SKILL_IDS = TradeSkillAttributes.IDS + fun id(path: String) = ResourceLocation.tryBuild(MOD_ID, path)!! private val gimmick = listOf( @@ -89,10 +89,6 @@ 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) - DefaultAttributeFactory.registerOverrides(DefaultAttributeImpl.OVERRIDES) - DefaultAttributeFactory.registerFunctions(DefaultAttributeImpl.FUNCTIONS) - DefaultAttributeFactory.registerEntityTypes(DefaultAttributeImpl.ENTITY_TYPES) - 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/api/attribute/DefaultAttributeImpl.kt b/src/main/kotlin/com/bibireden/playerex/api/attribute/DefaultAttributeImpl.kt deleted file mode 100644 index b4d8023c..00000000 --- a/src/main/kotlin/com/bibireden/playerex/api/attribute/DefaultAttributeImpl.kt +++ /dev/null @@ -1,171 +0,0 @@ -package com.bibireden.playerex.api.attribute - -import com.bibireden.data_attributes.api.attribute.StackingBehavior -import com.bibireden.data_attributes.api.attribute.StackingFormula -import com.bibireden.data_attributes.config.functions.AttributeFunction -import com.bibireden.data_attributes.config.models.OverridesConfigModel.AttributeOverride -import com.bibireden.data_attributes.data.EntityTypeData -import com.bibireden.playerex.compat.CompatUtils -import com.bibireden.playerex.ext.id -import de.dafuqs.additionalentityattributes.AdditionalEntityAttributes -import net.fabric_extras.ranged_weapon.api.EntityAttributes_RangedWeapon -import net.minecraft.resources.ResourceLocation -import net.minecraft.world.entity.ai.attributes.Attributes -import org.jetbrains.annotations.ApiStatus - -@ApiStatus.Internal -object DefaultAttributeImpl { - val OVERRIDES: Map = mutableMapOf( - PlayerEXAttributes.POISON_RESISTANCE.id to AttributeOverride( - smoothness = 1.0, - formula = StackingFormula.Diminished - ), - Attributes.KNOCKBACK_RESISTANCE.id to AttributeOverride( - smoothness = 1.0, - formula = StackingFormula.Diminished - ), - PlayerEXAttributes.MELEE_CRITICAL_DAMAGE.id to AttributeOverride( - smoothness = 1.0, - formula = StackingFormula.Diminished - ), - PlayerEXAttributes.RANGED_CRITICAL_DAMAGE.id to AttributeOverride( - smoothness = 1.0, - formula = StackingFormula.Diminished - ), - PlayerEXAttributes.WITHER_RESISTANCE.id to AttributeOverride( - smoothness = 1.0, - formula = StackingFormula.Diminished - ), - PlayerEXAttributes.FREEZE_RESISTANCE.id to AttributeOverride( - smoothness = 1.0, - formula = StackingFormula.Diminished - ), - PlayerEXAttributes.LIGHTNING_RESISTANCE.id to AttributeOverride( - smoothness = 1.0, - formula = StackingFormula.Diminished - ), - PlayerEXAttributes.HEALTH_REGENERATION.id to AttributeOverride( - smoothness = 1.0, - formula = StackingFormula.Diminished - ), - PlayerEXAttributes.HEAL_AMPLIFICATION.id to AttributeOverride( - smoothness = 1.0, - formula = StackingFormula.Diminished - ), - PlayerEXAttributes.FIRE_RESISTANCE.id to AttributeOverride( - smoothness = 1.0, - formula = StackingFormula.Diminished - ), - PlayerEXAttributes.MELEE_CRITICAL_CHANCE.id to AttributeOverride( - smoothness = 1.0, - formula = StackingFormula.Diminished - ), - PlayerEXAttributes.RANGED_CRITICAL_CHANCE.id to AttributeOverride( - smoothness = 1.0, - formula = StackingFormula.Diminished - ), - Attributes.LUCK.id to AttributeOverride( - smoothness = 1.0, - formula = StackingFormula.Diminished - ), - PlayerEXAttributes.EVASION.id to AttributeOverride( - smoothness = 1.0, - formula = StackingFormula.Diminished - ), - ).apply { - if (CompatUtils.isModLoaded("spell_power")) { - put(ModdedAttributes.SPELL_HASTE.id, AttributeOverride( - smoothness = 1.0, - formula = StackingFormula.Diminished - )) - put(ModdedAttributes.SPELL_CRITICAL_CHANCE.id, AttributeOverride( - smoothness = 1.0, - formula = StackingFormula.Diminished - )) - } - } - - val FUNCTIONS: Map> = mapOf( - PlayerEXAttributes.CONSTITUTION.id to listOf( - AttributeFunction(Attributes.MAX_HEALTH.id, StackingBehavior.Add, 0.5), - AttributeFunction(Attributes.ARMOR.id, StackingBehavior.Add, 0.25), - AttributeFunction(AdditionalEntityAttributes.MAGIC_PROTECTION.id, StackingBehavior.Add, 0.25), - AttributeFunction(AdditionalEntityAttributes.LUNG_CAPACITY.id, StackingBehavior.Add, 0.01), - AttributeFunction(PlayerEXAttributes.POISON_RESISTANCE.id, StackingBehavior.Add, 0.01), - ), - PlayerEXAttributes.STRENGTH.id to listOf( - AttributeFunction(Attributes.ATTACK_DAMAGE.id, StackingBehavior.Multiply, 0.02), - AttributeFunction(Attributes.KNOCKBACK_RESISTANCE.id, StackingBehavior.Add, 0.01), - AttributeFunction(PlayerEXAttributes.MELEE_CRITICAL_DAMAGE.id, StackingBehavior.Add, 0.005), - AttributeFunction(PlayerEXAttributes.BREAKING_SPEED.id, StackingBehavior.Add, 0.01), - ), - PlayerEXAttributes.DEXTERITY.id to listOf( - AttributeFunction(Attributes.ATTACK_SPEED.id, StackingBehavior.Multiply, 0.01), - AttributeFunction(PlayerEXAttributes.RANGED_CRITICAL_DAMAGE.id, StackingBehavior.Add, 0.005), - AttributeFunction(EntityAttributes_RangedWeapon.HASTE.id, StackingBehavior.Multiply, 0.02), - AttributeFunction(EntityAttributes_RangedWeapon.DAMAGE.id, StackingBehavior.Multiply, 0.02), - ), - PlayerEXAttributes.INTELLIGENCE.id to mutableListOf( - AttributeFunction(AdditionalEntityAttributes.DROPPED_EXPERIENCE.id, StackingBehavior.Multiply, 0.01), - AttributeFunction(PlayerEXAttributes.WITHER_RESISTANCE.id, StackingBehavior.Add, 0.01), - // todo: max mana? (see archon) - ).apply { - if (CompatUtils.isModLoaded("spell_power")) { - add(AttributeFunction(ModdedAttributes.SPELL_HASTE.id, StackingBehavior.Add, 2.0)) - } - }, - PlayerEXAttributes.FOCUS.id to listOf( - AttributeFunction(PlayerEXAttributes.HEALTH_REGENERATION.id, StackingBehavior.Add, 0.01), - AttributeFunction(PlayerEXAttributes.HEAL_AMPLIFICATION.id, StackingBehavior.Add, 0.05), - AttributeFunction(PlayerEXAttributes.FREEZE_RESISTANCE.id, StackingBehavior.Add, 0.01), - AttributeFunction(PlayerEXAttributes.LIGHTNING_RESISTANCE.id, StackingBehavior.Add, 0.01), - AttributeFunction(PlayerEXAttributes.FIRE_RESISTANCE.id, StackingBehavior.Add, 0.01), - ), - PlayerEXAttributes.LUCKINESS.id to mutableListOf( - AttributeFunction(PlayerEXAttributes.MELEE_CRITICAL_CHANCE.id, StackingBehavior.Add, 0.02), - AttributeFunction(PlayerEXAttributes.RANGED_CRITICAL_CHANCE.id, StackingBehavior.Add, 0.02), - // loot table chance?? wh- - AttributeFunction(Attributes.LUCK.id, StackingBehavior.Add, 0.05), - AttributeFunction(PlayerEXAttributes.EVASION.id, StackingBehavior.Add, 0.01), - ).apply { - if (CompatUtils.isModLoaded("spell_power")) { - add(AttributeFunction(ModdedAttributes.SPELL_CRITICAL_CHANCE.id, StackingBehavior.Add, 2.0)) - } - }, - ) - val ENTITY_TYPES: Map = mapOf( - ResourceLocation.tryBuild("minecraft", "player")!! to EntityTypeData(mapOf( - PlayerEXAttributes.LEVEL.id to 0.0, - PlayerEXAttributes.CONSTITUTION.id to 0.0, - PlayerEXAttributes.STRENGTH.id to 0.0, - PlayerEXAttributes.STRENGTH.id to 0.0, - PlayerEXAttributes.DEXTERITY.id to 0.0, - PlayerEXAttributes.INTELLIGENCE.id to 0.0, - PlayerEXAttributes.LUCKINESS.id to 0.0, - PlayerEXAttributes.EVASION.id to 0.0, - PlayerEXAttributes.LIFESTEAL.id to 0.0, - PlayerEXAttributes.FOCUS.id to 0.0, - PlayerEXAttributes.HEALTH_REGENERATION.id to 0.0, - PlayerEXAttributes.HEAL_AMPLIFICATION.id to 0.0, - PlayerEXAttributes.HEAL_AMPLIFICATION.id to 0.0, - PlayerEXAttributes.MELEE_CRITICAL_DAMAGE.id to 0.0, - PlayerEXAttributes.MELEE_CRITICAL_CHANCE.id to 0.0, - PlayerEXAttributes.RANGED_CRITICAL_DAMAGE.id to 0.0, - PlayerEXAttributes.RANGED_CRITICAL_CHANCE.id to 0.0, - PlayerEXAttributes.FIRE_RESISTANCE.id to 0.0, - PlayerEXAttributes.FREEZE_RESISTANCE.id to 0.0, - PlayerEXAttributes.LIGHTNING_RESISTANCE.id to 0.0, - PlayerEXAttributes.POISON_RESISTANCE.id to 0.0, - PlayerEXAttributes.WITHER_RESISTANCE.id to 0.0, - PlayerEXAttributes.BREAKING_SPEED.id to 1.0, - - TradeSkillAttributes.ENCHANTING.id to 0.0, - TradeSkillAttributes.LOGGING.id to 0.0, - TradeSkillAttributes.ALCHEMY.id to 0.0, - TradeSkillAttributes.FISHING.id to 0.0, - TradeSkillAttributes.MINING.id to 0.0, - TradeSkillAttributes.SMITHING.id to 0.0, - TradeSkillAttributes.FARMING.id to 0.0 - )) - ) -} \ No newline at end of file diff --git a/src/main/kotlin/com/bibireden/playerex/ext/EntityAttribute.kt b/src/main/kotlin/com/bibireden/playerex/ext/EntityAttribute.kt index 10928a96..cb5c8252 100644 --- a/src/main/kotlin/com/bibireden/playerex/ext/EntityAttribute.kt +++ b/src/main/kotlin/com/bibireden/playerex/ext/EntityAttribute.kt @@ -5,5 +5,11 @@ import net.minecraft.resources.ResourceLocation import net.minecraft.world.entity.ai.attributes.Attribute +/** + * Expects the [Attribute] to be registered by the time it is invoked. + * + * Returns an unresolved [ResourceLocation] if invalid. + * Do not use this in static initialization. + * */ val Attribute.id: ResourceLocation - get() = BuiltInRegistries.ATTRIBUTE.getKey(this)!! \ No newline at end of file + get() = BuiltInRegistries.ATTRIBUTE.getKey(this) ?: ResourceLocation.tryBuild("unresolved", "id")!! \ No newline at end of file diff --git a/src/main/resources/data/playerex/data_attributes/entity_types/stock.json b/src/main/resources/data/playerex/data_attributes/entity_types/stock.json new file mode 100644 index 00000000..11701155 --- /dev/null +++ b/src/main/resources/data/playerex/data_attributes/entity_types/stock.json @@ -0,0 +1,34 @@ +{ + "entries": { + "minecraft:player": { + "playerex:level": 0.0, + "playerex:constitution": 0.0, + "playerex:strength": 0.0, + "playerex:dexterity": 0.0, + "playerex:intelligence": 0.0, + "playerex:luckiness": 0.0, + "playerex:evasion": 0.0, + "playerex:lifesteal": 0.0, + "playerex:focus": 0.0, + "playerex:health_regeneration": 0.0, + "playerex:heal_amplification": 0.0, + "playerex:melee_crit_damage": 0.0, + "playerex:melee_crit_chance": 0.0, + "playerex:ranged_crit_damage": 0.0, + "playerex:ranged_crit_chance": 0.0, + "playerex:fire_resistance": 0.0, + "playerex:freeze_resistance": 0.0, + "playerex:lightning_resistance": 0.0, + "playerex:poison_resistance": 0.0, + "playerex:wither_resistance": 0.0, + "playerex:breaking_speed": 1.0, + "playerex:enchanting": 0.0, + "playerex:logging": 0.0, + "playerex:alchemy": 0.0, + "playerex:fishing": 0.0, + "playerex:mining": 0.0, + "playerex:smithing": 0.0, + "playerex:farming": 0.0 + } + } +} \ No newline at end of file diff --git a/src/main/resources/data/playerex/data_attributes/functions/stock.json b/src/main/resources/data/playerex/data_attributes/functions/stock.json new file mode 100644 index 00000000..57e991d4 --- /dev/null +++ b/src/main/resources/data/playerex/data_attributes/functions/stock.json @@ -0,0 +1,146 @@ +{ + "entries": { + "playerex:luckiness": [ + { + "id": "playerex:melee_crit_chance", + "behavior": "Add", + "value": 0.02 + }, + { + "id": "playerex:ranged_crit_chance", + "behavior": "Add", + "value": 0.02 + }, + { + "id": "minecraft:generic.luck", + "behavior": "Add", + "value": 0.05 + }, + { + "id": "playerex:evasion", + "behavior": "Add", + "value": 0.01 + }, + { + "id": "spell_power:critical_chance", + "behavior": "Add", + "value": 0.02 + } + ], + "playerex:dexterity": [ + { + "id": "minecraft:generic.attack_speed", + "behavior": "Multiply", + "value": 0.01 + }, + { + "id": "playerex:ranged_crit_damage", + "behavior": "Add", + "value": 0.005 + }, + { + "id": "ranged_weapon:haste", + "behavior": "Multiply", + "value": 0.02 + }, + { + "id": "ranged_weapon:damage", + "behavior": "Multiply", + "value": 0.02 + } + ], + "playerex:constitution": [ + { + "id": "minecraft:generic.max_health", + "behavior": "Add", + "value": 0.5 + }, + { + "id": "minecraft:generic.armor", + "behavior": "Add", + "value": 0.25 + }, + { + "id": "additionalentityattributes:generic.magic_protection", + "behavior": "Add", + "value": 0.25 + }, + { + "id": "additionalentityattributes:generic.lung_capacity", + "behavior": "Add", + "value": 0.01 + }, + { + "id": "playerex:poison_resistance", + "behavior": "Add", + "value": 0.01 + } + ], + "playerex:intelligence": [ + { + "id": "additionalentityattributes:player.dropped_experience", + "behavior": "Multiply", + "value": 0.01 + }, + { + "id": "playerex:wither_resistance", + "behavior": "Add", + "value": 0.01 + }, + { + "id": "spell_power:haste", + "behavior": "Add", + "value": 0.002 + } + ], + "playerex:focus": [ + { + "id": "playerex:health_regeneration", + "behavior": "Add", + "value": 0.0015 + }, + { + "id": "playerex:heal_amplification", + "behavior": "Add", + "value": 2.0E-4 + }, + { + "id": "playerex:freeze_resistance", + "behavior": "Add", + "value": 0.01 + }, + { + "id": "playerex:lightning_resistance", + "behavior": "Add", + "value": 0.01 + }, + { + "id": "playerex:fire_resistance", + "behavior": "Add", + "value": 0.01 + } + ], + "playerex:strength": [ + { + "id": "minecraft:generic.attack_damage", + "behavior": "Multiply", + "value": 0.02 + }, + { + "id": "minecraft:generic.knockback_resistance", + "behavior": "Add", + "value": 0.1 + }, + { + "id": "playerex:melee_crit_damage", + "behavior": "Add", + "value": 0.005 + }, + { + "id": "playerex:breaking_speed", + "behavior": "Add", + "value": 1.0 + } + ] + } +} \ No newline at end of file diff --git a/src/main/resources/data/playerex/data_attributes/overrides/stock.json b/src/main/resources/data/playerex/data_attributes/overrides/stock.json new file mode 100644 index 00000000..8124a16f --- /dev/null +++ b/src/main/resources/data/playerex/data_attributes/overrides/stock.json @@ -0,0 +1,148 @@ +{ + "entries": { + "playerex:lightning_resistance": { + "enabled": true, + "min": 0.0, + "max": 1.0, + "smoothness": 1.0, + "min_fallback": 0.0, + "max_fallback": 1.0, + "formula": "Diminished" + }, + "spell_power:haste": { + "enabled": true, + "min": 100.0, + "max": 1000.0, + "smoothness": 1.0, + "min_fallback": 100.0, + "max_fallback": 1000.0, + "formula": "Diminished" + }, + "playerex:ranged_crit_damage": { + "enabled": true, + "min": 0.0, + "max": 1000000.0, + "smoothness": 1.0, + "min_fallback": 0.0, + "max_fallback": 1000000.0, + "formula": "Diminished" + }, + "minecraft:generic.knockback_resistance": { + "enabled": true, + "min": 0.0, + "max": 1.0, + "smoothness": 1.0, + "min_fallback": 0.0, + "max_fallback": 1.0, + "formula": "Diminished" + }, + "minecraft:generic.luck": { + "enabled": true, + "min": -1024.0, + "max": 1024.0, + "smoothness": 1.0, + "min_fallback": -1024.0, + "max_fallback": 1024.0, + "formula": "Diminished" + }, + "playerex:poison_resistance": { + "enabled": true, + "min": 0.0, + "max": 1.0, + "smoothness": 1.0, + "min_fallback": 0.0, + "max_fallback": 1.0, + "formula": "Diminished" + }, + "playerex:melee_crit_damage": { + "enabled": true, + "min": 0.0, + "max": 1.0, + "smoothness": 1.0, + "min_fallback": 0.0, + "max_fallback": 1.0, + "formula": "Diminished" + }, + "playerex:wither_resistance": { + "enabled": true, + "min": 0.0, + "max": 1.0, + "smoothness": 1.0, + "min_fallback": 0.0, + "max_fallback": 1.0, + "formula": "Diminished" + }, + "playerex:freeze_resistance": { + "enabled": true, + "min": 0.0, + "max": 1.0, + "smoothness": 1.0, + "min_fallback": 0.0, + "max_fallback": 1.0, + "formula": "Diminished" + }, + "playerex:health_regeneration": { + "enabled": true, + "min": 0.0, + "max": 100.0, + "smoothness": 1.0, + "min_fallback": 0.0, + "max_fallback": 100.0, + "formula": "Diminished" + }, + "playerex:heal_amplification": { + "enabled": true, + "min": 0.0, + "max": 100.0, + "smoothness": 1.0, + "min_fallback": 0.0, + "max_fallback": 100.0, + "formula": "Diminished" + }, + "playerex:ranged_crit_chance": { + "enabled": true, + "min": 0.0, + "max": 1.0, + "smoothness": 1.0, + "min_fallback": 0.0, + "max_fallback": 1.0, + "formula": "Diminished" + }, + "playerex:evasion": { + "enabled": true, + "min": 0.0, + "max": 100.0, + "smoothness": 1.0, + "min_fallback": 0.0, + "max_fallback": 100.0, + "formula": "Diminished" + }, + "playerex:melee_crit_chance": { + "enabled": true, + "min": 0.0, + "max": 1.0, + "smoothness": 1.0, + "min_fallback": 0.0, + "max_fallback": 1.0, + "formula": "Diminished" + }, + "playerex:fire_resistance": { + "enabled": true, + "min": 0.0, + "max": 1.0, + "smoothness": 1.0, + "min_fallback": 0.0, + "max_fallback": 1.0, + "formula": "Diminished" + }, + "spell_power:critical_chance": { + "enabled": true, + "min": 100.0, + "max": 1000.0, + "smoothness": 1.0, + "min_fallback": 100.0, + "max_fallback": 1000.0, + "formula": "Diminished" + } + } +} \ No newline at end of file