diff --git a/ffa-server/build.gradle.kts b/ffa-server/build.gradle.kts index e82b98f..742e0d9 100644 --- a/ffa-server/build.gradle.kts +++ b/ffa-server/build.gradle.kts @@ -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) diff --git a/settings.gradle.kts b/settings.gradle.kts index 26e904e..d18ad29 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -17,5 +17,6 @@ include(":hero-api") include(":katara") include(":aang") include(":toph") +include(":spiderman") include(":ffa-server") diff --git a/spiderman/build.gradle.kts b/spiderman/build.gradle.kts new file mode 100644 index 0000000..896b28c --- /dev/null +++ b/spiderman/build.gradle.kts @@ -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")) +} + diff --git a/spiderman/src/main/java/gg/norisk/heroes/spiderman/mixin/CobwebBlockMixin.java b/spiderman/src/main/java/gg/norisk/heroes/spiderman/mixin/CobwebBlockMixin.java new file mode 100644 index 0000000..2ec9de5 --- /dev/null +++ b/spiderman/src/main/java/gg/norisk/heroes/spiderman/mixin/CobwebBlockMixin.java @@ -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); + } + } +} diff --git a/spiderman/src/main/java/gg/norisk/heroes/spiderman/mixin/PlayerEntityMixin.java b/spiderman/src/main/java/gg/norisk/heroes/spiderman/mixin/PlayerEntityMixin.java new file mode 100644 index 0000000..ee4fec0 --- /dev/null +++ b/spiderman/src/main/java/gg/norisk/heroes/spiderman/mixin/PlayerEntityMixin.java @@ -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 cir) { + PlayerEntity self = (PlayerEntity) (Object) this; + WallClimbAbilityKt.handleWallClimbCheck(self, cir); + CobwebClimbAbilityKt.handleCobwebClimbCheck(self, cir); + } +} diff --git a/spiderman/src/main/kotlin/gg/norisk/heroes/spiderman/SpidermanManager.kt b/spiderman/src/main/kotlin/gg/norisk/heroes/spiderman/SpidermanManager.kt new file mode 100644 index 0000000..1410eee --- /dev/null +++ b/spiderman/src/main/kotlin/gg/norisk/heroes/spiderman/SpidermanManager.kt @@ -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) + } +} diff --git a/spiderman/src/main/kotlin/gg/norisk/heroes/spiderman/ability/CobwebClimbAbility.kt b/spiderman/src/main/kotlin/gg/norisk/heroes/spiderman/ability/CobwebClimbAbility.kt new file mode 100644 index 0000000..99e48f7 --- /dev/null +++ b/spiderman/src/main/kotlin/gg/norisk/heroes/spiderman/ability/CobwebClimbAbility.kt @@ -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) { + if (player.getHero() == SpidermanManager.Spiderman && !player.isSpectator && player.blockStateAtPos.block == Blocks.COBWEB) { + cir.returnValue = true + } +} diff --git a/spiderman/src/main/kotlin/gg/norisk/heroes/spiderman/ability/SwingAbility.kt b/spiderman/src/main/kotlin/gg/norisk/heroes/spiderman/ability/SwingAbility.kt new file mode 100644 index 0000000..972d521 --- /dev/null +++ b/spiderman/src/main/kotlin/gg/norisk/heroes/spiderman/ability/SwingAbility.kt @@ -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() + } + } + } +} diff --git a/spiderman/src/main/kotlin/gg/norisk/heroes/spiderman/ability/ThrowWebsAbility.kt b/spiderman/src/main/kotlin/gg/norisk/heroes/spiderman/ability/ThrowWebsAbility.kt new file mode 100644 index 0000000..0d7da5c --- /dev/null +++ b/spiderman/src/main/kotlin/gg/norisk/heroes/spiderman/ability/ThrowWebsAbility.kt @@ -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) + } + } + } +} diff --git a/spiderman/src/main/kotlin/gg/norisk/heroes/spiderman/ability/WallClimbAbility.kt b/spiderman/src/main/kotlin/gg/norisk/heroes/spiderman/ability/WallClimbAbility.kt new file mode 100644 index 0000000..84cbdbb --- /dev/null +++ b/spiderman/src/main/kotlin/gg/norisk/heroes/spiderman/ability/WallClimbAbility.kt @@ -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) { + if (player.getHero() == SpidermanManager.Spiderman && !player.isSpectator && player.horizontalCollision) { + cir.returnValue = true + } +} diff --git a/spiderman/src/main/kotlin/gg/norisk/heroes/spiderman/client/render/SwingWebRenderer.kt b/spiderman/src/main/kotlin/gg/norisk/heroes/spiderman/client/render/SwingWebRenderer.kt new file mode 100644 index 0000000..5d9c2ea --- /dev/null +++ b/spiderman/src/main/kotlin/gg/norisk/heroes/spiderman/client/render/SwingWebRenderer.kt @@ -0,0 +1,153 @@ +package gg.norisk.heroes.spiderman.client.render + +import gg.norisk.heroes.spiderman.entity.SwingWebEntity +import net.minecraft.client.render.* +import net.minecraft.client.render.entity.EntityRenderer +import net.minecraft.client.render.entity.EntityRendererFactory +import net.minecraft.client.render.entity.state.EntityRenderState +import net.minecraft.client.render.entity.state.EntityRenderState.LeashData +import net.minecraft.client.render.item.ItemRenderState +import net.minecraft.client.util.math.MatrixStack +import net.minecraft.item.ItemStack +import net.minecraft.item.Items +import net.minecraft.item.ModelTransformationMode +import net.minecraft.util.math.MathHelper +import org.joml.Matrix4f + +private val webItemStack = ItemStack(Items.COBWEB) + +class SwingWebRenderState : EntityRenderState() { + val itemRenderState = ItemRenderState() +} + +class SwingWebRenderer(context: EntityRendererFactory.Context) : + EntityRenderer(context) { + private val itemModelManager = context.itemModelManager + + override fun createRenderState(): SwingWebRenderState? { + return SwingWebRenderState() + } + + override fun updateRenderState(entity: SwingWebEntity, state: SwingWebRenderState, tickDelta: Float) { + super.updateRenderState(entity, state, tickDelta) + itemModelManager.updateForNonLivingEntity( + state.itemRenderState, + webItemStack, + ModelTransformationMode.GROUND, + entity) + if (state.leashData == null) { + state.leashData = LeashData() + } + state.leashData!!.startPos = entity.pos + val owner = entity.owner + state.leashData!!.endPos = if (owner != null) owner.pos.add(0.0, owner.height / 2.0, 0.0) else entity.pos + } + + override fun render(state: SwingWebRenderState, + matrixStack: MatrixStack, + vertexConsumerProvider: VertexConsumerProvider, + light: Int) { + matrixStack.push() + matrixStack.multiply(dispatcher.rotation) + matrixStack.scale(4f, 4f, 4f) + state.itemRenderState.render( + matrixStack, + vertexConsumerProvider, + light, + OverlayTexture.DEFAULT_UV) + matrixStack.pop() + + val leashData = state.leashData + if (leashData != null) { + renderLeash(matrixStack, vertexConsumerProvider, leashData) + } + } + + // net.minecraft.client.render.entity.EntityRenderer.renderLeash + private fun renderLeash(matrices: MatrixStack, vertexConsumers: VertexConsumerProvider, leashData: LeashData) { + val g = (leashData.endPos.x - leashData.startPos.x).toFloat() + val h = (leashData.endPos.y - leashData.startPos.y).toFloat() + val i = (leashData.endPos.z - leashData.startPos.z).toFloat() + val j = MathHelper.inverseSqrt(g * g + i * i) * 0.025f / 2.0f + val k = i * j + val l = g * j + matrices.push() + matrices.translate(leashData.offset) + val vertexConsumer = vertexConsumers.getBuffer(RenderLayer.getLeash()) + val matrix4f = matrices.peek().getPositionMatrix() + + for (m in 0..24) { + renderLeashSegment( + vertexConsumer, + matrix4f, + g, + h, + i, + leashData.leashedEntityBlockLight, + leashData.leashHolderBlockLight, + leashData.leashedEntitySkyLight, + leashData.leashHolderSkyLight, + 0.025f, + 0.025f, + k, + l, + m, + false) + } + + for (m in 24 downTo 0) { + renderLeashSegment( + vertexConsumer, + matrix4f, + g, + h, + i, + leashData.leashedEntityBlockLight, + leashData.leashHolderBlockLight, + leashData.leashedEntitySkyLight, + leashData.leashHolderSkyLight, + 0.025f, + 0.0f, + k, + l, + m, + true) + } + + matrices.pop() + } + + // net.minecraft.client.render.entity.EntityRenderer.renderLeashSegment + private fun renderLeashSegment(vertexConsumer: VertexConsumer, + matrix: Matrix4f, + leashedEntityX: Float, + leashedEntityY: Float, + leashedEntityZ: Float, + leashedEntityBlockLight: Int, + leashHolderBlockLight: Int, + leashedEntitySkyLight: Int, + leashHolderSkyLight: Int, + f: Float, + g: Float, + h: Float, + i: Float, + segmentIndex: Int, + isLeashKnot: Boolean) { + val j = segmentIndex.toFloat() / 24.0f + val k = MathHelper.lerp(j, leashedEntityBlockLight.toFloat(), leashHolderBlockLight.toFloat()).toInt() + val l = MathHelper.lerp(j, leashedEntitySkyLight.toFloat(), leashHolderSkyLight.toFloat()).toInt() + val m = LightmapTextureManager.pack(k, l) + val n = if (segmentIndex % 2 == (if (isLeashKnot) 1 else 0)) 0.7f else 1.0f + val o = 0.75f * n + val p = 0.75f * n + val q = 0.75f * n + val r = leashedEntityX * j + val s = if (leashedEntityY > 0.0f) + leashedEntityY * j * j + else + leashedEntityY - leashedEntityY * (1.0f - j) * (1.0f - j) + val t = leashedEntityZ * j + vertexConsumer.vertex(matrix, r - h * 6, s + g, t + i * 6).color(o, p, q, 1.0f).light(m) + vertexConsumer.vertex(matrix, r + h * 6, s + f - g, t - i * 6).color(o, p, q, 1.0f).light(m) + } +} diff --git a/spiderman/src/main/kotlin/gg/norisk/heroes/spiderman/entity/FallingCobwebEntity.kt b/spiderman/src/main/kotlin/gg/norisk/heroes/spiderman/entity/FallingCobwebEntity.kt new file mode 100644 index 0000000..664f710 --- /dev/null +++ b/spiderman/src/main/kotlin/gg/norisk/heroes/spiderman/entity/FallingCobwebEntity.kt @@ -0,0 +1,41 @@ +package gg.norisk.heroes.spiderman.entity + +import gg.norisk.heroes.common.utils.toBlockPos +import net.minecraft.block.Blocks +import net.minecraft.entity.FallingBlockEntity +import net.minecraft.entity.MovementType +import net.minecraft.entity.player.PlayerEntity +import net.minecraft.util.math.Direction + +class FallingCobwebEntity(owner: PlayerEntity) + : FallingBlockEntity(owner.world, owner.x, owner.eyePos.y, owner.z, Blocks.COBWEB.defaultState) { + override fun tick() { + if (blockState.isAir) { + discard() + return + } + timeFalling++ + applyGravity() + move(MovementType.SELF, velocity) + tickBlockCollision() + tickPortalTeleportation() + if (!world.isClient && isAlive) { + if (!isOnGround) { + Direction.entries.forEach { + val pos = this.pos.add(0.5, 0.5, 0.5).add(it.doubleVector).toBlockPos() + if (!world.getBlockState(pos).isAir) { + if (world.setBlockState(blockPos, blockState, 3)) { + discard() + } + return + } + } + val y = blockPos.y + if ((timeFalling > 100 && (y <= world.bottomY || y > world.topYInclusive)) || timeFalling > 600) { + discard() + } + } + velocity = velocity.multiply(0.98) + } + } +} diff --git a/spiderman/src/main/kotlin/gg/norisk/heroes/spiderman/entity/SwingWebEntity.kt b/spiderman/src/main/kotlin/gg/norisk/heroes/spiderman/entity/SwingWebEntity.kt new file mode 100644 index 0000000..0357ee7 --- /dev/null +++ b/spiderman/src/main/kotlin/gg/norisk/heroes/spiderman/entity/SwingWebEntity.kt @@ -0,0 +1,75 @@ +package gg.norisk.heroes.spiderman.entity + +import gg.norisk.datatracker.entity.getSyncedData +import gg.norisk.datatracker.entity.setSyncedData +import net.minecraft.client.network.ClientPlayerEntity +import net.minecraft.entity.Entity +import net.minecraft.entity.EntityType +import net.minecraft.entity.player.PlayerEntity +import net.minecraft.entity.projectile.PersistentProjectileEntity +import net.minecraft.item.ItemStack +import net.minecraft.item.Items +import net.minecraft.server.world.ServerWorld +import net.minecraft.util.TypeFilter +import net.minecraft.util.hit.BlockHitResult +import net.minecraft.util.hit.EntityHitResult +import net.minecraft.world.World +import kotlin.math.abs + +class SwingWebEntity(entityType: EntityType, world: World) : PersistentProjectileEntity(entityType, world) { + var ropeLength: Double + get() = this.getSyncedData("RopeLength") ?: 0.0 + set(value) = this.setSyncedData("RopeLength", value) + var currentLength = -1.0 + + override fun getDefaultItemStack(): ItemStack? = ItemStack(Items.COBWEB) + + override fun tick() { + super.tick() + + val player = owner as? PlayerEntity? ?: return + val distance = distanceTo(player) + if (player.isDead || distance > ropeLength || player.isSneaking) { + discard() + } + + if (isInGround && distance > currentLength) { + if (world.isClient && player is ClientPlayerEntity) { + if (player.input.playerInput.jump) { + val vec = player.pos.subtract(player.pos).multiply(0.5) + player.addVelocity(vec.horizontal) + } + } + val vec = pos.subtract(player.pos).multiply(0.05) + player.addVelocity(vec.multiply(abs(vec.x) * 2, 1.0, abs(vec.z) * 2)) + } + } + + private fun onHit() { + if (owner == null) { + return + } + currentLength = distanceTo(owner).toDouble() * 0.85 + if (!world.isClient) { + for (entity in (world as ServerWorld).getEntitiesByType(TypeFilter.instanceOf(SwingWebEntity::class.java)) { true }) { + if (entity.owner == owner && entity != this) { + entity.discard() + } + } + } + owner?.addVelocity(pos.subtract(owner?.pos).multiply(0.1, 0.001, 0.1)) + } + + override fun onEntityHit(entityHitResult: EntityHitResult) = onHit() + + override fun onBlockHit(blockHitResult: BlockHitResult) { + super.onBlockHit(blockHitResult) + onHit() + } + + override fun getGravity(): Double = 0.01 + + override fun canHit(entity: Entity): Boolean = entity != owner + + override fun tryPickup(player: PlayerEntity): Boolean = false +} diff --git a/spiderman/src/main/kotlin/gg/norisk/heroes/spiderman/registry/EntityRegistry.kt b/spiderman/src/main/kotlin/gg/norisk/heroes/spiderman/registry/EntityRegistry.kt new file mode 100644 index 0000000..5f83971 --- /dev/null +++ b/spiderman/src/main/kotlin/gg/norisk/heroes/spiderman/registry/EntityRegistry.kt @@ -0,0 +1,29 @@ +package gg.norisk.heroes.spiderman.registry + +import gg.norisk.heroes.common.HeroesManager +import gg.norisk.heroes.spiderman.SpidermanManager.toId +import gg.norisk.heroes.spiderman.entity.SwingWebEntity +import net.minecraft.entity.EntityType +import net.minecraft.entity.SpawnGroup +import net.minecraft.registry.Registries +import net.minecraft.registry.Registry +import net.minecraft.registry.RegistryKey +import net.minecraft.registry.RegistryKeys + +object EntityRegistry { + val SWING_WEB = Registry.register( + Registries.ENTITY_TYPE, + "swing_web".toId(), + EntityType.Builder.create(::SwingWebEntity, SpawnGroup.MISC) + .requires(HeroesManager.heroesFlag) + .dimensions(0.3125f, 0.3125f) + .build(keyOf("swing_web")) + ) + + fun init() { + } + + private fun keyOf(id: String): RegistryKey> { + return RegistryKey.of(RegistryKeys.ENTITY_TYPE, id.toId()) + } +} diff --git a/spiderman/src/main/kotlin/gg/norisk/heroes/spiderman/registry/EntityRendererRegistry.kt b/spiderman/src/main/kotlin/gg/norisk/heroes/spiderman/registry/EntityRendererRegistry.kt new file mode 100644 index 0000000..ed4208a --- /dev/null +++ b/spiderman/src/main/kotlin/gg/norisk/heroes/spiderman/registry/EntityRendererRegistry.kt @@ -0,0 +1,10 @@ +package gg.norisk.heroes.spiderman.registry + +import gg.norisk.heroes.spiderman.client.render.SwingWebRenderer +import net.fabricmc.fabric.api.client.rendering.v1.EntityRendererRegistry + +object EntityRendererRegistry { + fun init() { + EntityRendererRegistry.register(EntityRegistry.SWING_WEB, ::SwingWebRenderer) + } +} diff --git a/spiderman/src/main/resources/assets/hero-api/textures/hero/spiderman/icon.png b/spiderman/src/main/resources/assets/hero-api/textures/hero/spiderman/icon.png new file mode 100644 index 0000000..6b903d1 Binary files /dev/null and b/spiderman/src/main/resources/assets/hero-api/textures/hero/spiderman/icon.png differ diff --git a/spiderman/src/main/resources/assets/spiderman/icon.png b/spiderman/src/main/resources/assets/spiderman/icon.png new file mode 100644 index 0000000..6b903d1 Binary files /dev/null and b/spiderman/src/main/resources/assets/spiderman/icon.png differ diff --git a/spiderman/src/main/resources/assets/spiderman/lang/de_de.json b/spiderman/src/main/resources/assets/spiderman/lang/de_de.json new file mode 100644 index 0000000..1aecd34 --- /dev/null +++ b/spiderman/src/main/resources/assets/spiderman/lang/de_de.json @@ -0,0 +1,10 @@ +{ + "text.hero.spiderman.description": "Spiderman Beschreibung???", + "hero.spiderman.ability.swing.description": "Scheiße ein Netz und schwinge.", + "heroes.property.web_shoot_power": "Schusskraft", + "heroes.property.web_shoot_power.description": "Die Kraft, mit der zu das Netz schießt.", + "heroes.property.rope_length": "Netzlänge", + "heroes.property.rope_length.description": "Die Länge deines Netzes.", + "hero.spiderman.ability.throw_webs.description": "Werfe Spinnennetze.", + "heroes.property.web_amount": "Menge" +} diff --git a/spiderman/src/main/resources/assets/spiderman/lang/en_us.json b/spiderman/src/main/resources/assets/spiderman/lang/en_us.json new file mode 100644 index 0000000..fd6484f --- /dev/null +++ b/spiderman/src/main/resources/assets/spiderman/lang/en_us.json @@ -0,0 +1,10 @@ +{ + "text.hero.spiderman.description": "Spiderman description???", + "hero.spiderman.ability.swing.description": "Shoot a web and swing.", + "heroes.property.web_shoot_power": "Web shoot power", + "heroes.property.web_shoot_power.description": "The shooting power.", + "heroes.property.rope_length": "Web rope length", + "heroes.property.rope_length.description": "The length of your web rope.", + "hero.spiderman.ability.throw_webs.description": "Throw cobwebs.", + "heroes.property.web_amount": "Amount" +} diff --git a/spiderman/src/main/resources/fabric.mod.json b/spiderman/src/main/resources/fabric.mod.json new file mode 100644 index 0000000..038641e --- /dev/null +++ b/spiderman/src/main/resources/fabric.mod.json @@ -0,0 +1,54 @@ +{ + "schemaVersion": 1, + "name": "Spiderman", + "id": "spiderman", + "version": "${version}", + "description": "Spiderman", + "authors": [ + "NoRiskk", + "Fabi.exe" + ], + "icon": "assets/spiderman/icon.png", + "license": "ARR", + "environment": "*", + "entrypoints": { + "main": [ + { + "adapter": "kotlin", + "value": "gg.norisk.heroes.spiderman.SpidermanManager" + } + ], + "client": [ + { + "adapter": "kotlin", + "value": "gg.norisk.heroes.spiderman.SpidermanManager" + } + ], + "server": [ + { + "adapter": "kotlin", + "value": "gg.norisk.heroes.spiderman.SpidermanManager" + } + ] + }, + "mixins": [ + "spiderman.mixins.json" + ], + "accessWidener": "spiderman.accesswidener", + "depends": { + "java": ">=21", + "minecraft": "*", + "fabric": "*", + "fabric-language-kotlin": "*" + }, + "custom": { + "modmenu": { + "badges": [ + "library" + ], + "parent": { + "id": "hero-api" + } + } + } +} diff --git a/spiderman/src/main/resources/spiderman.accesswidener b/spiderman/src/main/resources/spiderman.accesswidener new file mode 100644 index 0000000..6dce5c4 --- /dev/null +++ b/spiderman/src/main/resources/spiderman.accesswidener @@ -0,0 +1,2 @@ +accessWidener v2 named +accessible method net/minecraft/entity/FallingBlockEntity (Lnet/minecraft/world/World;DDDLnet/minecraft/block/BlockState;)V diff --git a/spiderman/src/main/resources/spiderman.mixins.json b/spiderman/src/main/resources/spiderman.mixins.json new file mode 100644 index 0000000..f8a07c6 --- /dev/null +++ b/spiderman/src/main/resources/spiderman.mixins.json @@ -0,0 +1,15 @@ +{ + "required": true, + "minVersion": "0.8", + "package": "gg.norisk.heroes.spiderman.mixin", + "compatibilityLevel": "JAVA_21", + "injectors": { + "defaultRequire": 1 + }, + "mixins": [ + "CobwebBlockMixin", + "PlayerEntityMixin" + ], + "client": [ + ] +}