diff --git a/ffa-server/src/main/java/gg/norisk/ffa/server/mixin/ServerPlayerEntityMixin.java b/ffa-server/src/main/java/gg/norisk/ffa/server/mixin/ServerPlayerEntityMixin.java index 0a4eeb3..c8aa6f0 100644 --- a/ffa-server/src/main/java/gg/norisk/ffa/server/mixin/ServerPlayerEntityMixin.java +++ b/ffa-server/src/main/java/gg/norisk/ffa/server/mixin/ServerPlayerEntityMixin.java @@ -3,6 +3,9 @@ import com.mojang.authlib.GameProfile; import gg.norisk.ffa.server.mechanics.KitEditor; import gg.norisk.ffa.server.mechanics.SoupHealing; +import gg.norisk.ffa.server.mechanics.TeamNerf; +import net.minecraft.entity.Entity; +import net.minecraft.entity.damage.DamageSource; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.Items; import net.minecraft.server.network.ServerPlayerEntity; @@ -13,6 +16,7 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(ServerPlayerEntity.class) public abstract class ServerPlayerEntityMixin extends PlayerEntity { @@ -20,10 +24,7 @@ public ServerPlayerEntityMixin(World world, BlockPos blockPos, float f, GameProf super(world, blockPos, f, gameProfile); } - @Inject( - method = "swingHand", - at = @At("HEAD") - ) + @Inject(method = "swingHand", at = @At("HEAD")) public void onSwing(Hand hand, CallbackInfo ci) { if (!KitEditor.INSTANCE.isUHC()) { ServerPlayerEntity player = (ServerPlayerEntity) (Object) this; @@ -33,4 +34,18 @@ public void onSwing(Hand hand, CallbackInfo ci) { } } } + + @Inject(method = "attack", at = @At("HEAD")) + public void onAttack(Entity target, CallbackInfo ci) { + if (target instanceof PlayerEntity) { + TeamNerf.INSTANCE.onAttack(this, (PlayerEntity) target); + } + } + + @Inject(method = "getDamageAgainst", at = @At("RETURN"), cancellable = true) + public void onGetDamageAgainst(Entity target, float baseDamage, DamageSource damageSource, CallbackInfoReturnable cir) { + if (target instanceof ServerPlayerEntity) { + cir.setReturnValue(TeamNerf.INSTANCE.getDamageAgainst((PlayerEntity) target, cir.getReturnValue())); + } + } } diff --git a/ffa-server/src/main/kotlin/gg/norisk/ffa/server/FFAServer.kt b/ffa-server/src/main/kotlin/gg/norisk/ffa/server/FFAServer.kt index 74aca2e..3996878 100644 --- a/ffa-server/src/main/kotlin/gg/norisk/ffa/server/FFAServer.kt +++ b/ffa-server/src/main/kotlin/gg/norisk/ffa/server/FFAServer.kt @@ -9,6 +9,7 @@ import gg.norisk.ffa.server.mechanics.Bounty import gg.norisk.ffa.server.mechanics.CombatTag import gg.norisk.ffa.server.mechanics.KillManager import gg.norisk.ffa.server.mechanics.KitEditor +import gg.norisk.ffa.server.mechanics.TeamNerf import gg.norisk.ffa.server.selector.SelectorServerManager import gg.norisk.ffa.server.world.MapPlacer import gg.norisk.ffa.server.world.WorldManager @@ -35,6 +36,7 @@ object FFAServer : ModInitializer { CombatTag.init() KillManager.init() InvseeCommand.init() + TeamNerf.init() } const val FFA_KEY = "hero-ffa" diff --git a/ffa-server/src/main/kotlin/gg/norisk/ffa/server/mechanics/TeamNerf.kt b/ffa-server/src/main/kotlin/gg/norisk/ffa/server/mechanics/TeamNerf.kt new file mode 100644 index 0000000..031f646 --- /dev/null +++ b/ffa-server/src/main/kotlin/gg/norisk/ffa/server/mechanics/TeamNerf.kt @@ -0,0 +1,51 @@ +package gg.norisk.ffa.server.mechanics + +import net.minecraft.entity.player.PlayerEntity +import net.silkmc.silk.core.task.mcCoroutineTask +import kotlin.math.pow +import kotlin.time.DurationUnit +import kotlin.time.toDuration + +object TeamNerf { + val hits: MutableMap> = mutableMapOf() + + fun init() { + mcCoroutineTask(sync = true, client = false, period = 1.toDuration(DurationUnit.SECONDS)) { + hits.forEach { + val player = it.key + if (!player.isAlive) { + hits.remove(player) + return@forEach + } + val hitMap = it.value + hitMap.forEach { target, time -> + if (!target.isAlive || player.world != target.world || player.distanceTo(target) > 20) { + hitMap.remove(target) + } + } + } + } + } + + fun onAttack(player: PlayerEntity, target: PlayerEntity) { + if (player == target) { + return + } + if (!hits.contains(player)) { + hits[player] = mutableMapOf() + } + val hits = hits[player]!! + hits[target] = System.currentTimeMillis() + } + + fun getDamageAgainst(target: PlayerEntity, damage: Float): Float { + val hits = hits[target] ?: mapOf() + var teamSize = 0 + for (hit in hits) { + if (hit.value + 1000*10 > System.currentTimeMillis()) { + teamSize++ + } + } + return if (teamSize > 1) damage * teamSize.toFloat().pow(-0.8f) else damage + } +} \ No newline at end of file