Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions ffa-server/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ dependencies {
api(project(":katara", configuration = "namedElements"))
api(project(":aang", configuration = "namedElements"))
api(project(":toph", configuration = "namedElements"))
api(project(":spiderman", configuration = "namedElements"))

modApi(libs.bundles.fabric)
modApi(libs.bundles.silk)
Expand Down
1 change: 1 addition & 0 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,6 @@ include(":hero-api")
include(":katara")
include(":aang")
include(":toph")
include(":spiderman")
include(":ffa-server")

18 changes: 18 additions & 0 deletions spiderman/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
version = "1.0.0"

dependencies {
implementation(project(":hero-api", configuration = "namedElements"))
implementation(project(":datatracker", configuration = "namedElements"))

modApi(libs.bundles.fabric)
modApi(libs.bundles.silk)
modApi(libs.bundles.performance)
modApi(libs.owolib)
modApi(libs.geckolib)
modApi(libs.emoteLib)
}

loom {
accessWidenerPath.set(file("src/main/resources/spiderman.accesswidener"))
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package gg.norisk.heroes.spiderman.mixin;

import gg.norisk.heroes.spiderman.ability.CobwebClimbAbilityKt;
import net.minecraft.block.BlockState;
import net.minecraft.block.CobwebBlock;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
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(CobwebBlock.class)
public class CobwebBlockMixin {
@Inject(method = "onEntityCollision", at = @At("HEAD"), cancellable = true)
public void onEntityCollision(BlockState state, World world, BlockPos pos, Entity entity, CallbackInfo ci) {
if (entity instanceof PlayerEntity player) {
CobwebClimbAbilityKt.handleCobwebCollision(player, ci);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package gg.norisk.heroes.spiderman.mixin;

import gg.norisk.heroes.spiderman.ability.CobwebClimbAbilityKt;
import gg.norisk.heroes.spiderman.ability.WallClimbAbilityKt;
import net.minecraft.entity.player.PlayerEntity;
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.CallbackInfoReturnable;

@Mixin(PlayerEntity.class)
public class PlayerEntityMixin {
@Inject(method = "isClimbing", at = @At("RETURN"), cancellable = true)
private void isClimbing(CallbackInfoReturnable<Boolean> cir) {
PlayerEntity self = (PlayerEntity) (Object) this;
WallClimbAbilityKt.handleWallClimbCheck(self, cir);
CobwebClimbAbilityKt.handleCobwebClimbCheck(self, cir);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package gg.norisk.heroes.spiderman

import gg.norisk.heroes.common.hero.Hero
import gg.norisk.heroes.common.hero.HeroManager.registerHero
import gg.norisk.heroes.spiderman.ability.SwingAbility
import gg.norisk.heroes.spiderman.ability.ThrowWebsAbility
import gg.norisk.heroes.spiderman.registry.EntityRegistry
import gg.norisk.heroes.spiderman.registry.EntityRendererRegistry
import net.fabricmc.api.ClientModInitializer
import net.fabricmc.api.DedicatedServerModInitializer
import net.fabricmc.api.ModInitializer
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents
import net.minecraft.util.Identifier
import org.apache.logging.log4j.LogManager
import java.awt.Color

object SpidermanManager : ModInitializer, ClientModInitializer, DedicatedServerModInitializer {
private const val MOD_ID = "spiderman"
val logger = LogManager.getLogger(MOD_ID)
fun String.toId() = Identifier.of(MOD_ID, this)

override fun onInitialize() {
logger.info("Starting $MOD_ID Hero...")
EntityRegistry.init()
}

override fun onInitializeClient() {
ClientLifecycleEvents.CLIENT_STARTED.register {
registerHero(Spiderman)
}
EntityRendererRegistry.init()
}

override fun onInitializeServer() {
registerHero(Spiderman)
}

val Spiderman by Hero("Spiderman") {
color = Color.RED.rgb
ability(SwingAbility)
ability(ThrowWebsAbility)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package gg.norisk.heroes.spiderman.ability

import gg.norisk.heroes.common.hero.getHero
import gg.norisk.heroes.spiderman.SpidermanManager
import net.minecraft.block.Blocks
import net.minecraft.entity.player.PlayerEntity
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable

fun handleCobwebCollision(player: PlayerEntity, ci: CallbackInfo) {
if (player.getHero() == SpidermanManager.Spiderman && !player.isSpectator) {
ci.cancel()
}
}

fun handleCobwebClimbCheck(player: PlayerEntity, cir: CallbackInfoReturnable<Boolean>) {
if (player.getHero() == SpidermanManager.Spiderman && !player.isSpectator && player.blockStateAtPos.block == Blocks.COBWEB) {
cir.returnValue = true

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this if is unnecessary, just do

cir.returnValue = player.getHero() == SpidermanManager.Spiderman && !player.isSpectator && player.blockStateAtPos.block == Blocks.COBWEB

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package gg.norisk.heroes.spiderman.ability

import gg.norisk.heroes.client.option.HeroKeyBindings
import gg.norisk.heroes.common.HeroesManager.client
import gg.norisk.heroes.common.ability.NumberProperty
import gg.norisk.heroes.common.ability.operation.AddValueTotal
import gg.norisk.heroes.common.hero.ability.AbilityScope
import gg.norisk.heroes.common.hero.ability.implementation.PressAbility
import gg.norisk.heroes.spiderman.entity.SwingWebEntity
import gg.norisk.heroes.spiderman.registry.EntityRegistry
import io.wispforest.owo.ui.component.Components
import io.wispforest.owo.ui.core.Component
import net.minecraft.entity.player.PlayerEntity
import net.minecraft.item.Items
import net.minecraft.server.world.ServerWorld
import net.minecraft.util.Identifier
import net.minecraft.util.TypeFilter
import net.silkmc.silk.core.annotations.ExperimentalSilkApi
import net.silkmc.silk.core.entity.directionVector
import net.silkmc.silk.core.item.itemStack

val ropeLength = NumberProperty(50.0, 3, "Rope length", AddValueTotal(5.0, 10.0, 15.0, 20.0), 10).apply {
icon = {
Components.item(Items.FIREWORK_ROCKET.defaultStack)
}
}

val webShootPower = NumberProperty(1.0, 3, "Web shoot power", AddValueTotal(1.4, 1.9, 2.5), 20).apply {
icon = {
Components.item(Items.FIREWORK_ROCKET.defaultStack)
}
}

@OptIn(ExperimentalSilkApi::class)
object SwingAbility : PressAbility("Swing") {
init {
client {
keyBind = HeroKeyBindings.firstKeyBind
}
properties = listOf(ropeLength, webShootPower)
cooldownProperty = buildCooldown(60.0, 5, AddValueTotal(-10.0, -5.0, -5.0, -5.0, -10.0))
}

override fun getIconComponent(): Component {
return Components.item(itemStack(Items.STRING) {})
}

override fun getBackgroundTexture(): Identifier {
return Identifier.of("textures/block/packed_mud.png")
}

override fun onStart(player: PlayerEntity, abilityScope: AbilityScope) {
if (player.world is ServerWorld) {
val web = SwingWebEntity(EntityRegistry.SWING_WEB, player.world)
web.setPosition(player.eyePos)
web.owner = player
web.velocity = player.directionVector.multiply(webShootPower.getValue(player.uuid))
web.ropeLength = ropeLength.getValue(player.uuid)
player.world.spawnEntity(web)
}
}

override fun onDisable(player: PlayerEntity) {
val world = player.world as ServerWorld
for (entity in world.getEntitiesByType(TypeFilter.instanceOf(SwingWebEntity::class.java)) { true }) {
if (entity.owner == player) {
entity.discard()
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package gg.norisk.heroes.spiderman.ability

import gg.norisk.heroes.client.option.HeroKeyBindings
import gg.norisk.heroes.common.HeroesManager.client
import gg.norisk.heroes.common.ability.NumberProperty
import gg.norisk.heroes.common.ability.operation.AddValueTotal
import gg.norisk.heroes.common.hero.ability.AbilityScope
import gg.norisk.heroes.common.hero.ability.implementation.PressAbility
import gg.norisk.heroes.spiderman.entity.FallingCobwebEntity
import io.wispforest.owo.ui.component.Components
import io.wispforest.owo.ui.core.Component
import net.minecraft.entity.player.PlayerEntity
import net.minecraft.item.Items
import net.minecraft.server.world.ServerWorld
import net.minecraft.util.Identifier
import net.silkmc.silk.core.annotations.ExperimentalSilkApi
import net.silkmc.silk.core.entity.directionVector
import net.silkmc.silk.core.item.itemStack

val webAmount = NumberProperty(1.0, 4, "Web amount", AddValueTotal(1.0, 1.0, 2.0, 2.0)).apply {
icon = {
Components.item(Items.COBWEB.defaultStack)
}
}

@OptIn(ExperimentalSilkApi::class)
object ThrowWebsAbility : PressAbility("Throw webs") {
init {
client {
keyBind = HeroKeyBindings.secondKeyBind
}
properties = listOf(webAmount)
cooldownProperty = buildCooldown(90.0, 5, AddValueTotal(-9.0, -9.0, -9.0, -9.0, -9.0))
}

override fun getIconComponent(): Component {
return Components.item(itemStack(Items.COBWEB) {})
}

override fun getBackgroundTexture(): Identifier {
return Identifier.of("textures/block/packed_mud.png")
}

override fun onStart(player: PlayerEntity, abilityScope: AbilityScope) {
if (player.world is ServerWorld) {
repeat(webAmount.getValue(player.uuid).toInt()) {
val web = FallingCobwebEntity(player)
web.velocity = player.directionVector.multiply(0.6).addRandom(player.world.random, 0.3f)
player.world.spawnEntity(web)
}
}
Comment on lines +45 to +51

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use early returns, they help with code readablity and maintainability

        if (player.world !is ServerWorld) {
            return
        }
        // Continue with your code

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package gg.norisk.heroes.spiderman.ability

import gg.norisk.heroes.common.hero.getHero
import gg.norisk.heroes.spiderman.SpidermanManager
import net.minecraft.entity.player.PlayerEntity
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable

fun handleWallClimbCheck(player: PlayerEntity, cir: CallbackInfoReturnable<Boolean>) {
if (player.getHero() == SpidermanManager.Spiderman && !player.isSpectator && player.horizontalCollision) {
cir.returnValue = true
Comment on lines +9 to +10

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This as well can be shortened

cir.returnValue = player.getHero() == SpidermanManager.Spiderman && !player.isSpectator && player.horizontalCollision

}
}
Loading