Skip to content

Commit

Permalink
Merge branch '1.20.1/fabric' into 1.20.1/dev
Browse files Browse the repository at this point in the history
  • Loading branch information
bibi-reden committed Dec 13, 2024
2 parents 1c692ae + 1592556 commit 3706c04
Show file tree
Hide file tree
Showing 15 changed files with 536 additions and 29 deletions.
13 changes: 11 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
**This slates the first official release of the new PlayerEX. It had been stable for a while, although the UI was not fully completed.**
## PlayerEX Is Now Officially Released :)

**This slates the first official release of the new PlayerEX. It had been stable for a while, although the UI was not fully completed until now.**

## Additions 🍎
- Finished the PlayerEX UI to the point where it is ready for release.
- There is now a component set on the right of the UI that has a list of current pages. Use it in order to navigate between multiple mods who use the registry.
- Completely fleshed out the UI with meters and other metrics such as current health and lung capacity along with experience levels to keep track of what you currently have, updated based on your current state.
- Completely fleshed out the UI with meters and other metrics such as current health and lung capacity along with experience levels to keep track of what you currently have, updated based on your current state.
- Added Weapon & Armor Leveling (created by `naomieow` [much appreciated])
- Items and weapons in loot tables can be generated with a level.
- Added configuration related to armor and weapon leveling.
- The range they can generate in is different based on dimension.
- Non-Vanilla dimensions follow the overworld range.
- Weapon XP increases by a value specified in the config when a mob is killed.
- Thank you `RedstoneWizard08` for contributing to this system!
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -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-beta.12
mod_version=4.0.0+1.20.1
maven_group=com.bibireden.playerex
archives_base_name=playerex-directors-cut

Expand Down
85 changes: 66 additions & 19 deletions src/main/java/com/bibireden/playerex/mixin/ItemStackMixin.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,7 @@
import net.minecraft.world.InteractionResultHolder;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.ai.attributes.Attribute;
import net.minecraft.world.entity.ai.attributes.AttributeInstance;
import net.minecraft.world.entity.ai.attributes.AttributeModifier;
import net.minecraft.world.entity.ai.attributes.Attributes;
import net.minecraft.world.entity.ai.attributes.*;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.TooltipFlag;
Expand All @@ -39,22 +36,22 @@
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;

import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.*;
import java.util.function.Consumer;

@Mixin(ItemStack.class)
abstract class ItemStackMixin {
@Shadow
public abstract boolean hurt(int amount, RandomSource random, @Nullable ServerPlayer serverPlayer);

@Shadow
public abstract CompoundTag getOrCreateTag();

@Inject(method = "use(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/entity/player/Player;Lnet/minecraft/world/InteractionHand;)Lnet/minecraft/world/InteractionResultHolder;", at = @At(value = "HEAD"), cancellable = true)
public void preventUse(Level level, Player player, InteractionHand usedHand, CallbackInfoReturnable<InteractionResultHolder<ItemStack>> cir) {
if (!PlayerEX.CONFIG.getFeatureSettings().getItemBreakingEnabled()) return;

ItemStack stack = (ItemStack)(Object)this;
ItemStack stack = (ItemStack) (Object) this;
if (PlayerEXUtil.isBroken(stack)) {
cir.setReturnValue(InteractionResultHolder.fail(stack));
}
Expand All @@ -64,7 +61,7 @@ public void preventUse(Level level, Player player, InteractionHand usedHand, Cal
public void preventUseOnBlock(UseOnContext context, CallbackInfoReturnable<InteractionResult> cir) {
if (!PlayerEX.CONFIG.getFeatureSettings().getItemBreakingEnabled()) return;

ItemStack stack = (ItemStack)(Object)this;
ItemStack stack = (ItemStack) (Object) this;
if (PlayerEXUtil.isBroken(stack)) {
cir.setReturnValue(InteractionResult.FAIL);
}
Expand All @@ -74,7 +71,7 @@ public void preventUseOnBlock(UseOnContext context, CallbackInfoReturnable<Inter
public void preventDamage(int amount, RandomSource random, ServerPlayer user, CallbackInfoReturnable<Boolean> cir) {
if (!PlayerEX.CONFIG.getFeatureSettings().getItemBreakingEnabled()) return;

ItemStack stack = (ItemStack)(Object)this;
ItemStack stack = (ItemStack) (Object) this;
if (PlayerEXUtil.isBroken(stack)) {
cir.setReturnValue(true);
}
Expand All @@ -83,10 +80,10 @@ public void preventDamage(int amount, RandomSource random, ServerPlayer user, Ca
@Inject(method = "hurtAndBreak(ILnet/minecraft/world/entity/LivingEntity;Ljava/util/function/Consumer;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/ItemStack;shrink(I)V"), cancellable = true)
public <T extends LivingEntity> void preventBreak(int amount, T entity, Consumer<T> onBroken, CallbackInfo ci) {
if (!PlayerEX.CONFIG.getFeatureSettings().getItemBreakingEnabled()) return;
ItemStack stack = (ItemStack)(Object)this;
if (stack.getItem().builtInRegistryHolder().is(PlayerEXTags.UNBREAKABLE_ITEMS)) {
ItemStack stack = (ItemStack) (Object) this;
if (stack.getItemHolder().is(PlayerEXTags.UNBREAKABLE_ITEMS)) {
if (!PlayerEXUtil.isBroken(stack)) {
CompoundTag tag = stack.getTag();
CompoundTag tag = stack.getOrCreateTag();
tag.putBoolean("broken", true);
stack.setTag(tag);
}
Expand All @@ -98,20 +95,26 @@ public <T extends LivingEntity> void preventBreak(int amount, T entity, Consumer
public void removeBrokenOnRepair(int damage, CallbackInfo ci) {
if (!PlayerEX.CONFIG.getFeatureSettings().getItemBreakingEnabled()) return;

ItemStack stack = (ItemStack)(Object)this;
ItemStack stack = (ItemStack) (Object) this;
if (PlayerEXUtil.isBroken(stack) && damage < stack.getDamageValue()) {
CompoundTag tag = stack.getTag();
CompoundTag tag = stack.getOrCreateTag();
tag.putBoolean("broken", false);
stack.setTag(tag);
}
}

@Inject(method = "getAttributeModifiers(Lnet/minecraft/world/entity/EquipmentSlot;)Lcom/google/common/collect/Multimap;", at = @At(value = "RETURN"), cancellable = true)
public void preventArmour(EquipmentSlot slot, CallbackInfoReturnable<Multimap<Attribute, AttributeModifier>> cir) {
public void modifyAttributeModifiers(EquipmentSlot slot, CallbackInfoReturnable<Multimap<Attribute, AttributeModifier>> cir) {
if (!PlayerEX.CONFIG.getFeatureSettings().getItemBreakingEnabled()) return;

ItemStack stack = (ItemStack)(Object)this;
ItemStack stack = (ItemStack) (Object) this;
HashMultimap<Attribute, AttributeModifier> hashmap = HashMultimap.create(cir.getReturnValue());
if (PlayerEX.CONFIG.getWeaponLevelingSettings().getEnabled() && PlayerEXUtil.isWeapon(stack)) {
PlayerEXUtil.addToModifier(hashmap, Attributes.ATTACK_DAMAGE, getLevel() * PlayerEX.CONFIG.getWeaponLevelingSettings().getDamagePerLevel());
}
if (PlayerEX.CONFIG.getArmorLevelingSettings().getEnabled() && PlayerEXUtil.isArmor(stack)) {
PlayerEXUtil.addToModifier(hashmap, Attributes.ARMOR, getLevel() * PlayerEX.CONFIG.getArmorLevelingSettings().getArmorPerLevel());
}
if (PlayerEXUtil.isBroken(stack)) {
PlayerEXUtil.removeModifier(hashmap, Attributes.ARMOR);
PlayerEXUtil.removeModifier(hashmap, Attributes.ARMOR_TOUGHNESS);
Expand Down Expand Up @@ -166,7 +169,9 @@ public void preventArmour(EquipmentSlot slot, CallbackInfoReturnable<Multimap<At
}

@ModifyVariable(method = "getTooltipLines", at = @At(value = "STORE", ordinal = 1), ordinal = 1)
private double playerex$modifyAdditionAttributeKnockback(double original) { return original / 10.0; }
private double playerex$modifyAdditionAttributeKnockback(double original) {
return original / 10.0;
}

// todo: not sure about the implementation(s) here...
@Inject(method = "getTooltipLines", at = @At(value = "INVOKE", target = "Ljava/util/List;add(Ljava/lang/Object;)Z", ordinal = 7, shift = At.Shift.AFTER))
Expand Down Expand Up @@ -237,4 +242,46 @@ public void preventArmour(EquipmentSlot slot, CallbackInfoReturnable<Multimap<At
);
}
}

@Unique
private int getLevel() {
ItemStack itemStack = (ItemStack) (Object) this;
return itemStack.getOrCreateTag().getInt("Level");
}

@Unique
private int getXp() {
ItemStack itemStack = (ItemStack) (Object) this;
return itemStack.getOrCreateTag().getInt("Experience");
}

@Unique
private double getReduction() {
return Math.min(getLevel() * PlayerEX.CONFIG.getArmorLevelingSettings().getReductionPerLevel(), PlayerEX.CONFIG.getArmorLevelingSettings().getMaxReduction());
}

@Inject(method = "getTooltipLines", at = @At(value = "INVOKE", target = "Ljava/util/List;add(Ljava/lang/Object;)Z", ordinal = 0, shift = At.Shift.AFTER))
private void playerex$insertLevelTooltip(
Player player, TooltipFlag context,
CallbackInfoReturnable<List<Component>> info,
@Local List<Component> list
) {
ItemStack itemStack = (ItemStack) (Object) this;
if (PlayerEXUtil.isLevelable(itemStack)) {
list.add(Component.translatable("playerex.item.level", getLevel(), PlayerEXUtil.getMaxLevel(itemStack)));
list.add(Component.translatable("playerex.item.experience", getXp(), PlayerEXUtil.getRequiredXpForNextLevel(itemStack)));
}
}

@Inject(method = "getTooltipLines", at = @At(value = "INVOKE", target = "Ljava/util/List;add(Ljava/lang/Object;)Z", ordinal = 6, shift = At.Shift.AFTER))
private void playerex$insertReductionTooltip(
Player player, TooltipFlag context,
CallbackInfoReturnable<List<Component>> info,
@Local List<Component> list
) {
ItemStack itemStack = (ItemStack) (Object) this;
if (PlayerEXUtil.isArmor(itemStack)) {
list.add(Component.translatable("playerex.item.reduction", String.format("%.2f", getReduction())));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@
import net.minecraft.world.InteractionHand;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
Expand Down Expand Up @@ -70,4 +71,19 @@ public void preventAttack(InteractionHand hand, CallbackInfo ci) {
private boolean playerex$damage(boolean original, DamageSource source, float damage) {
return LivingEntityEvents.SHOULD_DAMAGE.invoker().shouldDamage((LivingEntity) (Object) this, source, damage);
}

@ModifyReturnValue(
method = "getDamageAfterArmorAbsorb(Lnet/minecraft/world/damagesource/DamageSource;F)F",
at = @At("RETURN")
)
public float applyDamageReduction(float original) {
LivingEntity self = (LivingEntity) (Object) this;
var total = 0d;
for (ItemStack slot : self.getArmorSlots()) {
total += Math.min(slot.getOrCreateTag().getInt("Level") * PlayerEX.CONFIG.getArmorLevelingSettings().getReductionPerLevel(), PlayerEX.CONFIG.getArmorLevelingSettings().getMaxReduction());
}
// 400 because 4 slots then percentage to decimal
total /= 400;
return (float) (original * (1 - total));
}
}
10 changes: 9 additions & 1 deletion src/main/kotlin/com/bibireden/playerex/PlayerEX.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,21 @@ import com.bibireden.playerex.api.event.LivingEntityEvents
import com.bibireden.playerex.api.event.PlayerEXSoundEvents
import com.bibireden.playerex.api.event.PlayerEntityEvents
import com.bibireden.playerex.config.PlayerEXConfig
import com.bibireden.playerex.config.PlayerEXConfigModel
import com.bibireden.playerex.config.PlayerEXConfigModel.Lifecycle
import com.bibireden.playerex.ext.component
import com.bibireden.playerex.factory.*
import com.bibireden.playerex.networking.NetworkingChannels
import com.bibireden.playerex.networking.NetworkingPackets
import com.bibireden.playerex.networking.registerServerbound
import com.bibireden.playerex.networking.types.UpdatePacketType
import com.bibireden.playerex.predicate.FilterCheck
import de.dafuqs.additionalentityattributes.AdditionalEntityAttributes
import eu.pb4.placeholders.api.Placeholders
import net.fabricmc.api.ModInitializer
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback
import net.fabricmc.fabric.api.entity.event.v1.ServerEntityCombatEvents
import net.fabricmc.fabric.api.entity.event.v1.ServerPlayerEvents
import net.fabricmc.fabric.api.loot.v2.LootTableEvents
import net.fabricmc.fabric.api.networking.v1.ServerLoginConnectionEvents
import net.minecraft.core.Registry
import net.minecraft.core.registries.BuiltInRegistries
Expand Down Expand Up @@ -79,18 +81,24 @@ object PlayerEX : ModInitializer {
LivingEntityEvents.ON_DAMAGE.register(EventFactory::onDamage)
LivingEntityEvents.SHOULD_DAMAGE.register(EventFactory::shouldDamage)

LootTableEvents.MODIFY.register(EventFactory::onModifyLootTable)

PlayerEntityEvents.ON_CRITICAL.register(EventFactory::onCritAttack)
PlayerEntityEvents.SHOULD_CRITICAL.register(EventFactory::attackIsCrit)

DamageFactory.forEach(PlayerEXAPI::registerDamageModification)
RefundFactory.forEach(PlayerEXAPI::registerRefundCondition)

ServerEntityCombatEvents.AFTER_KILLED_OTHER_ENTITY.register(EventFactory::entityWasKilled)

PlaceholderFactory.STORE.forEach(Placeholders::register)

Registry.register(BuiltInRegistries.SOUND_EVENT, PlayerEXSoundEvents.LEVEL_UP_SOUND.location, PlayerEXSoundEvents.LEVEL_UP_SOUND)
Registry.register(BuiltInRegistries.SOUND_EVENT, PlayerEXSoundEvents.SPEND_SOUND.location, PlayerEXSoundEvents.SPEND_SOUND)
Registry.register(BuiltInRegistries.SOUND_EVENT, PlayerEXSoundEvents.REFUND_SOUND.location, PlayerEXSoundEvents.REFUND_SOUND)

Registry.register(BuiltInRegistries.LOOT_FUNCTION_TYPE, id("filtered"), FilterCheck.type())

EntityAttributeModifiedEvents.MODIFIED.register { attribute, entity, _, _, _ ->
if (entity?.level() == null) return@register // no entity & no world, skip

Expand Down
8 changes: 7 additions & 1 deletion src/main/kotlin/com/bibireden/playerex/api/PlayerEXTags.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,10 @@ import net.minecraft.world.item.Item
object PlayerEXTags {
@JvmField
val UNBREAKABLE_ITEMS: TagKey<Item> = TagKey.create(Registries.ITEM, PlayerEX.id("unbreakable"))
}

@JvmField
val WEAPONS: TagKey<Item> = TagKey.create(Registries.ITEM, PlayerEX.id("weapons"))

@JvmField
val ARMOR: TagKey<Item> = TagKey.create(Registries.ITEM, PlayerEX.id("armor"))
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,93 @@ class PlayerEXConfigModel {
@JvmField @Nest @Expanded var featureSettings = FeatureSettings()
@JvmField @Nest @Expanded var lifecycleSettings = LifecycleSettings()
@JvmField @Nest @Expanded var advancedSettings = AdvancedSettings()
@JvmField @Nest @Expanded var weaponLevelingSettings = WeaponXpSettings()
@JvmField @Nest @Expanded var armorLevelingSettings = ArmorXpSettings()

@SectionHeader("client_options")

@JvmField @Nest @Expanded var visualSettings = VisualSettings()
@JvmField @Nest @Expanded var soundSettings = SoundSettings()

// SERVER

data class ArmorXpSettings(
@Sync(SyncMode.OVERRIDE_CLIENT)
@JvmField
var enabled: Boolean = true,

@Sync(SyncMode.OVERRIDE_CLIENT)
@JvmField
var armorPerLevel: Double = 0.1,

@Sync(SyncMode.OVERRIDE_CLIENT)
@JvmField
var reductionPerLevel: Double = 0.1,

@Sync(SyncMode.OVERRIDE_CLIENT)
@JvmField
@RangeConstraint(min = 0.0, max = 25.0)
var maxReduction: Double = 25.0,

@Sync(SyncMode.OVERRIDE_CLIENT)
@JvmField
var formula: String = "5x^(1.1)",

@Sync(SyncMode.OVERRIDE_CLIENT)
@JvmField
var xpFromPassive: Int = 10,

@Sync(SyncMode.OVERRIDE_CLIENT)
@JvmField
var xpFromHostile: Int = 20,

@Sync(SyncMode.OVERRIDE_CLIENT)
@JvmField
var xpFromMiniboss: Int = 50,

@Sync(SyncMode.OVERRIDE_CLIENT)
@JvmField
var xpFromBoss: Int = 100,

@Sync(SyncMode.OVERRIDE_CLIENT)
@JvmField
var maxLevel: Int = 500,
)

data class WeaponXpSettings(
@Sync(SyncMode.OVERRIDE_CLIENT)
@JvmField
var enabled: Boolean = true,

@Sync(SyncMode.OVERRIDE_CLIENT)
@JvmField
var damagePerLevel: Double = 0.1,

@Sync(SyncMode.OVERRIDE_CLIENT)
@JvmField
var formula: String = "5x^(1.1)",

@Sync(SyncMode.OVERRIDE_CLIENT)
@JvmField
var xpFromPassive: Int = 10,

@Sync(SyncMode.OVERRIDE_CLIENT)
@JvmField
var xpFromHostile: Int = 20,

@Sync(SyncMode.OVERRIDE_CLIENT)
@JvmField
var xpFromMiniboss: Int = 50,

@Sync(SyncMode.OVERRIDE_CLIENT)
@JvmField
var xpFromBoss: Int = 100,

@Sync(SyncMode.OVERRIDE_CLIENT)
@JvmField
var maxLevel: Int = 500,
)

data class LevelingSettings(
@Sync(SyncMode.OVERRIDE_CLIENT)
@JvmField
Expand Down
11 changes: 11 additions & 0 deletions src/main/kotlin/com/bibireden/playerex/ext/ItemStack.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.bibireden.playerex.ext

import net.minecraft.world.item.ItemStack

var ItemStack.level: Int
get() = this.orCreateTag.getInt("Level")
set(value) = this.orCreateTag.putInt("Level", value)

var ItemStack.xp: Int
get() = this.orCreateTag.getInt("Experience")
set(value) = this.orCreateTag.putInt("Experience", value)
Loading

0 comments on commit 3706c04

Please sign in to comment.